mirror of
https://gitlab.com/cable-mc/cobblemon.git
synced 2026-11-03 23:08:53 -05:00
Compare commits
224
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
da76b2fb94 | ||
|
|
87d8197dd0 | ||
|
|
2ed6f89d09 | ||
|
|
5947468cd9 | ||
|
|
7ba1507ac8 | ||
|
|
9fdffdc392 | ||
|
|
6a01fe3863 | ||
|
|
9b5a153e3f | ||
|
|
67f906dec2 | ||
|
|
0570afbe05 | ||
|
|
dfba2d27ab | ||
|
|
9c7cd4b616 | ||
|
|
9fe0e9c87e | ||
|
|
bd0e5a44bd | ||
|
|
229ec4176b | ||
|
|
323413efdc | ||
|
|
a309cc2522 | ||
|
|
cb782a2aa1 | ||
|
|
2c58dcb8ef | ||
|
|
d91cd4322c | ||
|
|
e48e492392 | ||
|
|
1f93994eba | ||
|
|
5210121b3d | ||
|
|
7fa3bf24d1 | ||
|
|
1128d7edf3 | ||
|
|
eef50a7237 | ||
|
|
f4140a097d | ||
|
|
b79dbcca80 | ||
|
|
5ac12a897a | ||
|
|
ae5f7c83f2 | ||
|
|
f14de9ab58 | ||
|
|
8a1c846c2c | ||
|
|
459e7d3490 | ||
|
|
5a9be8944f | ||
|
|
3bb941b087 | ||
|
|
384b496d76 | ||
|
|
4caa736e0b | ||
|
|
c3e9051918 | ||
|
|
fe940caafc | ||
|
|
c9d148ec9c | ||
|
|
e611bf4a77 | ||
|
|
8093822140 | ||
|
|
f695ec15f9 | ||
|
|
1f6c791ce6 | ||
|
|
570805fdf1 | ||
|
|
ddecb08bc7 | ||
|
|
a1b930a21f | ||
|
|
7728ff3892 | ||
|
|
0b38e063d2 | ||
|
|
4d7cfcdf61 | ||
|
|
e56dd6ef64 | ||
|
|
236b98fa78 | ||
|
|
ac61e0d4d0 | ||
|
|
d8956fd66f | ||
|
|
ffe005511d | ||
|
|
1e634a20b8 | ||
|
|
50a5a78dd4 | ||
|
|
76c2654399 | ||
|
|
f9f4745e93 | ||
|
|
c700674289 | ||
|
|
c4f0032eee | ||
|
|
d92986016b | ||
|
|
ab57e01242 | ||
|
|
0da1c740a4 | ||
|
|
a7979aa80c | ||
|
|
397d3c618d | ||
|
|
29f6feab6c | ||
|
|
ea5d3ae40f | ||
|
|
59804a4e08 | ||
|
|
072c67acad | ||
|
|
60bbe221de | ||
|
|
5f06dc214b | ||
|
|
a6607e585b | ||
|
|
20584f4507 | ||
|
|
9660f1f724 | ||
|
|
c8cbace800 | ||
|
|
a616a24923 | ||
|
|
12035dd589 | ||
|
|
9627b80b01 | ||
|
|
4e9cecc854 | ||
|
|
9d4b19b185 | ||
|
|
aee96d06aa | ||
|
|
23e3c585f7 | ||
|
|
c22a88079f | ||
|
|
2225402082 | ||
|
|
9197207431 | ||
|
|
47c7f7079c | ||
|
|
eb0c1dddfd | ||
|
|
e3dbfe6ff8 | ||
|
|
fac207f36b | ||
|
|
379e794848 | ||
|
|
9081a4b131 | ||
|
|
dc6d75b8ee | ||
|
|
bb297a4448 | ||
|
|
a93922c438 | ||
|
|
f7d21c80d7 | ||
|
|
9248d26fd4 | ||
|
|
b5ac54cd16 | ||
|
|
dc703e67f7 | ||
|
|
0930721865 | ||
|
|
644ff1772e | ||
|
|
3c7e0bebb6 | ||
|
|
0c0eea3876 | ||
|
|
5535140bb7 | ||
|
|
9b0ca1c16b | ||
|
|
052ff59f57 | ||
|
|
40e5ef1c46 | ||
|
|
5025977d23 | ||
|
|
922006afe7 | ||
|
|
46cc7cb04d | ||
|
|
fa3e3bbb1b | ||
|
|
afbdcce337 | ||
|
|
1fa113f5ac | ||
|
|
f680682f61 | ||
|
|
4d93d1244d | ||
|
|
6a7d5d2133 | ||
|
|
98397cd1da | ||
|
|
fc5a610394 | ||
|
|
504df5d998 | ||
|
|
3b4d3ebf50 | ||
|
|
def975c03f | ||
|
|
e67567e8dc | ||
|
|
23a42a29b3 | ||
|
|
8443b88c16 | ||
|
|
b71208299f | ||
|
|
136b5824b0 | ||
|
|
bacc482bf0 | ||
|
|
edb3f906f8 | ||
|
|
4171bf341b | ||
|
|
f9189b265f | ||
|
|
8e1fcc6f14 | ||
|
|
21c4d0233d | ||
|
|
61d53f3052 | ||
|
|
2e88d971f7 | ||
|
|
bfc1c66097 | ||
|
|
13d9f84d8d | ||
|
|
148eb130d9 | ||
|
|
eb07b0e03f | ||
|
|
1b8d416962 | ||
|
|
3030b544b5 | ||
|
|
b890d662f6 | ||
|
|
2a9bbc1d68 | ||
|
|
735817869a | ||
|
|
488e6dcf7a | ||
|
|
a0f32ea444 | ||
|
|
b426df7271 | ||
|
|
1543e06a06 | ||
|
|
d7b4ccb1e5 | ||
|
|
dedd449329 | ||
|
|
38c589658f | ||
|
|
182e06205d | ||
|
|
4c391645fe | ||
|
|
79bf50004a | ||
|
|
2f961bd7bf | ||
|
|
b72244a986 | ||
|
|
6710f25190 | ||
|
|
4089e5d7a9 | ||
|
|
0a49b5b17b | ||
|
|
34c40de429 | ||
|
|
6d02144401 | ||
|
|
561687ce0f | ||
|
|
20973c6724 | ||
|
|
bf10a4dcef | ||
|
|
565987a780 | ||
|
|
4f9a6c8e98 | ||
|
|
3a3e92d441 | ||
|
|
bc0dc809f9 | ||
|
|
92310847aa | ||
|
|
5bdc59830c | ||
|
|
17f524d3da | ||
|
|
4d0de2bb45 | ||
|
|
b3b8f56bb8 | ||
|
|
f036b83693 | ||
|
|
73fb31c2fc | ||
|
|
381787f39d | ||
|
|
2cb942a24b | ||
|
|
c79cb5731e | ||
|
|
4760bb15a4 | ||
|
|
aac881f23c | ||
|
|
da19c51566 | ||
|
|
396ab13164 | ||
|
|
37dd354155 | ||
|
|
acb1ebda19 | ||
|
|
5dddc05626 | ||
|
|
99890671bd | ||
|
|
9451ac5f46 | ||
|
|
a8e4e21ba1 | ||
|
|
f555ba3703 | ||
|
|
37677b3730 | ||
|
|
2a298b2268 | ||
|
|
ad3f94fb80 | ||
|
|
719660798e | ||
|
|
8d973a09e1 | ||
|
|
3579a86cde | ||
|
|
ba96a6a205 | ||
|
|
f07d2a9a9a | ||
|
|
2469067fd4 | ||
|
|
c10c91d86a | ||
|
|
d5fd2e9a07 | ||
|
|
45cc0ba579 | ||
|
|
1880a0a24e | ||
|
|
5f3a0b96cc | ||
|
|
7ab1610700 | ||
|
|
daad9f6c00 | ||
|
|
2b234b740e | ||
|
|
39e3983020 | ||
|
|
9d58cdb21c | ||
|
|
f05e35e792 | ||
|
|
a333e68620 | ||
|
|
2c2791ec69 | ||
|
|
635b09d82f | ||
|
|
46c3ff9db4 | ||
|
|
8bfc95c23a | ||
|
|
99d05b6ef7 | ||
|
|
1c0a14c819 | ||
|
|
fe5cd58801 | ||
|
|
c3bd007f5a | ||
|
|
dba24e104e | ||
|
|
35815e371b | ||
|
|
d0f8ae0565 | ||
|
|
b2e21969ca | ||
|
|
ea57c233a3 | ||
|
|
0d39b47f22 | ||
|
|
9f3a279b03 |
No files matched your search
+23
-74
@@ -1,88 +1,37 @@
|
||||
# Changelog
|
||||
## [1.8.3 (MONTH xth, 2026)](#1-8-3)
|
||||
## [1.9.0 (MONTH xth, 2026)](#1-9-0)
|
||||
|
||||
### Additions
|
||||
|
||||
### Cries added/updated for the following Pokémon
|
||||
- Hoppip
|
||||
- Skiploom
|
||||
- Jumpluff
|
||||
- Houndour
|
||||
- Houndoom
|
||||
- Wurmple
|
||||
- Silcoon
|
||||
- Beautifly
|
||||
- Cascoon
|
||||
- Dustox
|
||||
- Surskit
|
||||
- Masquerain
|
||||
- Torkoal
|
||||
- Starly
|
||||
- Staravia
|
||||
- Staraptor
|
||||
- Combee
|
||||
- Vespiquen
|
||||
- Dusknoir
|
||||
- Helioptile
|
||||
- Heliolisk
|
||||
- Grubbin
|
||||
- Charjabug
|
||||
- Vikavolt
|
||||
- Applin (updated)
|
||||
- Flapple (updated)
|
||||
- Appletun
|
||||
- Runerigus
|
||||
- Dipplin
|
||||
|
||||
### Model updates for the following Pokémon
|
||||
|
||||
### Animation updates for the following Pokémon
|
||||
- Vikavolt
|
||||
- Trainer bags and packs got added
|
||||
- You can craft and equip those to store additional items
|
||||
|
||||
### Changes
|
||||
- Changed the Misc icon in the Campfire Pot Recipe Book to Health Candy
|
||||
- Moved EXP Candies from the Medicine recipe book category to the Misc category
|
||||
- Removed Dynamic Lights data from the Magmarizer item for consistency with the block
|
||||
- Added `doPokemonPredation` gamerule, which controls aggressiveness of Pokémon with `hate_entity` brain task defined
|
||||
- Added `predation_chance` server config value, which controls the possibility of attacking the hated entity found by `hate_entity` brain task
|
||||
- Prehistoric Eroded Pillar generates slightly more frequently
|
||||
- Trading has been overhauled to allow offering multiple Pokémon, up to the entire party, in a single trade
|
||||
- Selected Pokémon are now highlighted in both parties with new party slot assets
|
||||
- Hovering an offered Pokémon now shows its summary, and clicking the active Pokémon no longer exits the summary view
|
||||
- The trade animation now moves the offered Pokémon towards the Poké Ball
|
||||
- Parties are compacted after a trade so no empty slots are left between Pokémon
|
||||
|
||||
### Fixes
|
||||
- Fixed datapacks with item interaction evolutions that don't specify an item crashing the world on load.
|
||||
- Fixed the Pokédex evolution tree crashing when a datapack's dex entry is missing an evolution's form.
|
||||
- Fixed the Pokédex evolution tree crashing with a stack overflow on evolutions that loop back on themselves.
|
||||
- Fixed the Pokédex evolution tree crashing when looking at a dex that is not part of the "National Dex" aggregate.
|
||||
- Fixed evolution trees not building properly when a Pokémon has several Pokédex entries for different regions.
|
||||
- Fixed form-changing evolutions sometimes resolving to the source form in the Pokédex evolution tree.
|
||||
- Broken datapack evolutions are now logged and skipped in the Pokédex evolution tree instead of crashing.
|
||||
- Fixed the `alpha` property having no tab completion in commands such as `/pokespawn`, `/pokegive` and `/pokeedit`, and added the missing `dmax_level`, `gmax_factor` and `tradable` aliases to tab completion
|
||||
- Fixed friendship booster items not being recognised as such
|
||||
- Fixed conflicts with other mods that would make use of recipe books in certain ways (Farmer's Delight Cooking Pot)
|
||||
- Fixed Pokémon battles stalling when a sidemod cancels the `THROWN_POKEBALL_HIT` hit event
|
||||
- Fixed choice feature tab completion in `spawnpokemon/pokegive/pokeedit` commands
|
||||
- Fixed MoLang that's targeting players intermittedly failing when they have died, needing them to relog
|
||||
- Fixed a NeoForge bug where none of the Cobblemon plants/berries could be placed into pots
|
||||
- Fixed party overlay not hiding when the player opens the Pokédex scanner
|
||||
- Added compat for AppleSkin
|
||||
- Fixed some display names having unintended font colours
|
||||
- Fixed `hate_entity` task focusing on its own entity
|
||||
- Thus enabled deadly warfare between Zangoose and Seviper
|
||||
- Prehistoric Frozen Pond, Prehistoric Frozen Spike, and Prehistoric Lush Den now generate
|
||||
- Fixed Frogadier floating in its battle_idle animation
|
||||
- Fixed absence or incorrect mergers in spawning conditions, making max height/depth of conditions to use the min value instead
|
||||
- Added stricter riding checks on server side to prevent possible packet forgery when player tries to ride pokemon
|
||||
- Fixed Pokémon cries and animation sounds played from GUIs, such as the starter selection screen and the Pokédex, being tied to the Master volume slider instead of Friendly Creatures
|
||||
|
||||
### Developer
|
||||
- Bumped NeoForge to `21.1.195` to get access to MixinExtras `0.5` and the expressions annotation
|
||||
- New Platform Event `PLAYER_RESPAWN` which is fired when a player respawns (either through death or returning from the end)
|
||||
- Platform Events `SERVER_PLAYER_TICK_PRE` and `SERVER_PLAYER_TICK_POST` no longer fire when the player is dead
|
||||
- it is now tied much closer to the actual entity rather than the player (or their connection)
|
||||
- Trade network packets (`TradeUpdatedPacket`, `UpdateTradeOfferPacket`, and `TradeCompletedPacket`) now receive an array of Pokémon instead of a single Pokémon to execute trades
|
||||
- `TradeEvent.Pre` and `TradeEvent.Post` now expose every Pokémon each participant receives (`tradeParticipant1Pokemon` and `tradeParticipant2Pokemon` are now lists), and their Molang context includes `trade_participant_1_pokemon_list` and `trade_participant_2_pokemon_list`
|
||||
|
||||
### Molang & Datapacks
|
||||
- Fixed `q.pokemon.nature` returning class instance instead of proper string value (`cobblemon:adamant`)
|
||||
- Fixed `q.entity.is_looking_at` result being always `1` for whatever entity passed as target
|
||||
- Added hate chance optional parameter to `hate_entity` task. `1.0` will make an entity always attack the target
|
||||
- `bag_categories` got added which control what kind of tabs and capabilities the Trainerbags have
|
||||
```json
|
||||
{
|
||||
"order": 1,
|
||||
"icon": "cobblemon:textures/item/medicine/potion.png",
|
||||
"whiteListTag": "cobblemon:bag/whitelist_consumables",
|
||||
"blackListTag": "cobblemon:bag/blacklist_consumables",
|
||||
"maxCount": 512
|
||||
}
|
||||
```
|
||||
- Bunch of default tags as white/blacklist got added to control what can be inserted the corresponding bag categories
|
||||
|
||||
### Particles
|
||||
|
||||
### Localization
|
||||
- Updated translations for:
|
||||
@@ -0,0 +1,107 @@
|
||||
# Changelog
|
||||
## [1.8.3 (October 25th, 2026)](#1-8-3)
|
||||
|
||||
### Additions
|
||||
- Added compatability with AppleSkin.
|
||||
|
||||
### New Rideable Pokémon
|
||||
- Vikavolt
|
||||
- Fearow
|
||||
|
||||
### Particles
|
||||
## New Move Animations
|
||||
- Water Shuriken
|
||||
|
||||
### Cries added/updated for the following Pokémon
|
||||
- Hoppip
|
||||
- Skiploom
|
||||
- Jumpluff
|
||||
- Houndour
|
||||
- Houndoom
|
||||
- Wurmple
|
||||
- Silcoon
|
||||
- Beautifly
|
||||
- Cascoon
|
||||
- Dustox
|
||||
- Surskit
|
||||
- Masquerain
|
||||
- Torkoal
|
||||
- Starly
|
||||
- Staravia
|
||||
- Staraptor
|
||||
- Combee
|
||||
- Vespiquen
|
||||
- Dusknoir
|
||||
- Helioptile
|
||||
- Heliolisk
|
||||
- Grubbin
|
||||
- Charjabug
|
||||
- Vikavolt
|
||||
- Applin (updated)
|
||||
- Flapple (updated)
|
||||
- Appletun
|
||||
- Runerigus
|
||||
- Dipplin
|
||||
|
||||
### Animation updates for the following Pokémon
|
||||
- Vikavolt
|
||||
- Magby
|
||||
- Magmar
|
||||
- Ninetales (+ Alolan)
|
||||
- Spearow
|
||||
- Fearow
|
||||
- Squawkabilly
|
||||
- Mudkip
|
||||
- Marshtomp
|
||||
- Swampert
|
||||
|
||||
### Changes
|
||||
- Changed the Misc icon in the Campfire Pot Recipe Book to Health Candy.
|
||||
- Moved EXP Candies from the Medicine recipe book category to the Misc category.
|
||||
- Removed Dynamic Lights data from the Magmarizer item for consistency with the block.
|
||||
- Added `doPokemonPredation` game rule, which controls aggressiveness of Pokémon with the `hate_entity` brain task defined.
|
||||
- Added `predation_chance` server config value, which controls the possibility of attacking the hated entity found in `hate_entity` brain tasks.
|
||||
- Prehistoric Eroded Pillar generates slightly more frequently.
|
||||
- Togekiss was changed from a jet-style mount to bird-style.
|
||||
|
||||
### Fixes
|
||||
- Fixed datapacks with item interaction evolutions that don't specify an item crashing the world on load.
|
||||
- Fixed the Pokédex evolution tree crashing when a datapack's dex entry is missing an evolution's form.
|
||||
- Fixed the Pokédex evolution tree crashing with a stack overflow on evolutions that loop back on themselves.
|
||||
- Fixed the Pokédex evolution tree crashing when looking at a dex that is not part of the "National Dex" aggregate.
|
||||
- Fixed some display names in the Pokédex evolution tree having unintended font colours.
|
||||
- Fixed evolution trees not building properly when a Pokémon has several Pokédex entries for different regions.
|
||||
- Fixed form-changing evolutions sometimes resolving to the source form in the Pokédex evolution tree.
|
||||
- Broken datapack evolutions are now logged and skipped in the Pokédex evolution tree instead of crashing.
|
||||
- Fixed the `alpha` property having no tab completion in commands such as `/pokespawn`, `/pokegive` and `/pokeedit`, and added the missing `dmax_level`, `gmax_factor` and `tradable` aliases to tab completion.
|
||||
- Fixed friendship booster items not being recognised as such.
|
||||
- Fixed conflicts with other mods that would make use of recipe books in certain ways (Farmer's Delight Cooking Pot).
|
||||
- Fixed Pokémon battles stalling when a sidemod cancels the `THROWN_POKEBALL_HIT` hit event.
|
||||
- Fixed choice feature tab completion in `spawnpokemon/pokegive/pokeedit` commands.
|
||||
- Fixed MoLang that's targeting players intermittedly failing when they have died, requiring them to relog.
|
||||
- Fixed a NeoForge bug where none of the Cobblemon plants/berries could be placed into pots.
|
||||
- Fixed party overlay not hiding when the player opens the Pokédex scanner.
|
||||
- Fixed `hate_entity` task focusing on its own entity, therefore enabling deadly warfare between Zangoose and Seviper.
|
||||
- Prehistoric Frozen Pond, Prehistoric Frozen Spike, and Prehistoric Lush Den now actually generate (oops).
|
||||
- Fixed Frogadier floating in its `battle_idle` animation.
|
||||
- Fixed absence or incorrect mergers in spawning conditions, causing the max height/depth of conditions to use the min value instead.
|
||||
- Added stricter riding checks on server side to prevent possible packet forgery when a player tries to ride Pokémon.
|
||||
- Fixed Pokémon cries and animation sounds played from GUIs, such as the starter selection screen and the Pokédex, being tied to the Master volume slider instead of Friendly Creatures.
|
||||
- Fixed Archeops T-posing during its `air_cry` animation.
|
||||
|
||||
### Developer
|
||||
- Bumped NeoForge to `21.1.195` to get access to MixinExtras `0.5` and the expressions annotation.
|
||||
- New Platform Event `PLAYER_RESPAWN` which is fired when a player respawns (either through death or returning from the end).
|
||||
- Platform Events `SERVER_PLAYER_TICK_PRE` and `SERVER_PLAYER_TICK_POST` no longer fire when the player is dead.
|
||||
- It is now tied much closer to the actual entity rather than the player or their connection.
|
||||
|
||||
### Molang & Datapacks
|
||||
- Fixed `q.pokemon.nature` returning class instance instead of proper string value (`cobblemon:adamant`).
|
||||
- Fixed `q.entity.is_looking_at` result being always `1` for whatever entity passed as the target parameter.
|
||||
- Added hate chance optional parameter to `hate_entity` task. `1.0` will make an entity always attack the target.
|
||||
|
||||
### Localization
|
||||
- Updated translations for:
|
||||
- Russian
|
||||
- Japanese
|
||||
- Brazilian Portuguese
|
||||
@@ -0,0 +1,25 @@
|
||||
# Changelog
|
||||
## [1.8.4 (October 27th, 2026)](#1-8-4)
|
||||
|
||||
### Changes
|
||||
- The Froakie line now blinks. The world will never be the same.
|
||||
|
||||
### Fixes
|
||||
- Fixed heaps of spawns not working. This was caused by us missing something before release. RIP.
|
||||
- Fixed a crash caused by Fearow blinking while you're riding one. Makes sense to me.
|
||||
- Fixed Minior's "Shields Down" ability being very broken.
|
||||
- Fixed Dusclops using Squirtle's cry sound (lol).
|
||||
- Fixed blank Cooking Pot recipe book entries and missing tabs on Fabric.
|
||||
- Fixed a hitbox issue with placeable Orb held items attached to a ceiling.
|
||||
- Fixed something sneaky. I'll tell you about it later.
|
||||
|
||||
### Molang & Datapacks
|
||||
- Added `q.target_fainted` function to move action effects that checks if any opponents fainted from the move.
|
||||
|
||||
### Particles
|
||||
- Updated Water Shuriken effect to be timed better when the opponent faints.
|
||||
|
||||
### Localization
|
||||
- Updated translations for:
|
||||
- Korean
|
||||
- Simplified Chinese
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* 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.bag;
|
||||
|
||||
import com.cobblemon.mod.common.item.bag.CobblemonBagContainer;
|
||||
|
||||
public interface BagEntity {
|
||||
CobblemonBagContainer cobblemon$getBagContainer();
|
||||
void cobblemon$setBagContainer(CobblemonBagContainer bagContainer);
|
||||
}
|
||||
@@ -23,6 +23,8 @@ import com.cobblemon.mod.common.api.tags.CobblemonItemTags;
|
||||
import com.cobblemon.mod.common.duck.PlayerDuck;
|
||||
import com.cobblemon.mod.common.duck.RidePassenger;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import com.cobblemon.mod.common.bag.BagEntity;
|
||||
import com.cobblemon.mod.common.item.bag.CobblemonBagContainer;
|
||||
import com.cobblemon.mod.common.pokedex.scanner.PokedexEntityData;
|
||||
import com.cobblemon.mod.common.pokedex.scanner.ScannableEntity;
|
||||
import com.cobblemon.mod.common.pokemon.FormData;
|
||||
@@ -56,6 +58,7 @@ import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.enchantment.EnchantmentHelper;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Vector3f;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
@@ -73,7 +76,7 @@ import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Mixin(Player.class)
|
||||
public abstract class PlayerMixin extends LivingEntity implements ScannableEntity, OrientationControllable, PlayerDuck, RidePassenger {
|
||||
public abstract class PlayerMixin extends LivingEntity implements ScannableEntity, OrientationControllable, PlayerDuck, RidePassenger, BagEntity {
|
||||
|
||||
@Unique
|
||||
private Vector3f cobblemon$driverInput;
|
||||
@@ -107,6 +110,8 @@ public abstract class PlayerMixin extends LivingEntity implements ScannableEntit
|
||||
|
||||
@Unique private Vec3 cobblemon$rideEyePos = Vec3.ZERO;
|
||||
|
||||
@Unique private CobblemonBagContainer cobblemon$cobblemonBagContainer = new CobblemonBagContainer();
|
||||
|
||||
protected PlayerMixin(EntityType<? extends LivingEntity> p_20966_, Level p_20967_) {
|
||||
super(p_20966_, p_20967_);
|
||||
}
|
||||
@@ -404,4 +409,37 @@ public abstract class PlayerMixin extends LivingEntity implements ScannableEntit
|
||||
original.call(target, strength, x, z);
|
||||
}
|
||||
|
||||
@Override @NotNull
|
||||
public CobblemonBagContainer cobblemon$getBagContainer() { return cobblemon$cobblemonBagContainer; }
|
||||
|
||||
@Override
|
||||
public void cobblemon$setBagContainer(CobblemonBagContainer bagContainer) { cobblemon$cobblemonBagContainer = bagContainer; }
|
||||
|
||||
@Inject(
|
||||
method = "readAdditionalSaveData(Lnet/minecraft/nbt/CompoundTag;)V",
|
||||
at = @At("TAIL")
|
||||
)
|
||||
private void cobblemon$readAdditionalSaveData(CompoundTag compound, CallbackInfo ci) {
|
||||
if (compound.contains("CobblemonBagData", 9)) {
|
||||
this.cobblemon$cobblemonBagContainer.fromTag(compound.getList("CobblemonBagData", 10), this.registryAccess());
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "addAdditionalSaveData(Lnet/minecraft/nbt/CompoundTag;)V",
|
||||
at = @At("TAIL")
|
||||
)
|
||||
private void cobblemon$addAdditionalSaveData(CompoundTag compound, CallbackInfo ci) {
|
||||
compound.put("CobblemonBagData", this.cobblemon$cobblemonBagContainer.createTag(this.registryAccess()));
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "dropEquipment()V",
|
||||
at = @At("TAIL")
|
||||
)
|
||||
private void cobblemon$dropCobblemonBag(CallbackInfo ci) {
|
||||
if (level().getGameRules().getBoolean(CobblemonGameRules.BAG_DROP_ITEMS)) {
|
||||
this.cobblemon$cobblemonBagContainer.dropAll((Player)(Object)this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,17 +15,23 @@ import com.cobblemon.mod.common.api.riding.RidingStyle;
|
||||
import com.cobblemon.mod.common.api.spawning.spawner.PlayerSpawner;
|
||||
import com.cobblemon.mod.common.api.spawning.spawner.PlayerSpawnerFactory;
|
||||
import com.cobblemon.mod.common.api.stats.CobblemonStats;
|
||||
import com.cobblemon.mod.common.block.HealingMachineBlock;
|
||||
import com.cobblemon.mod.common.duck.ServerLevelDuck;
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity;
|
||||
import com.cobblemon.mod.common.bag.BagEntity;
|
||||
import com.cobblemon.mod.common.world.gamerules.CobblemonGameRules;
|
||||
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
|
||||
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
|
||||
import com.llamalad7.mixinextras.sugar.Local;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
@@ -33,6 +39,9 @@ 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.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Mixin(ServerPlayer.class)
|
||||
public abstract class ServerPlayerMixin implements PlayerSpawnerAccessor {
|
||||
@@ -142,4 +151,25 @@ public abstract class ServerPlayerMixin implements PlayerSpawnerAccessor {
|
||||
((ServerLevelDuck) this.serverLevel()).cobblemon$getLevelResourceLocation()
|
||||
);
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "findRespawnAndUseSpawnBlock(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/core/BlockPos;FZZ)Ljava/util/Optional;",
|
||||
at = @At(value = "HEAD"),
|
||||
cancellable = true
|
||||
)
|
||||
private static void cobblemon$useHealthStationAsRespawn(ServerLevel level, BlockPos pos, float angle, boolean forced, boolean keepInventory, CallbackInfoReturnable<Optional<ServerPlayer.RespawnPosAngle>> cir) {
|
||||
BlockState state = level.getBlockState(pos);
|
||||
Block block = state.getBlock();
|
||||
if (block instanceof HealingMachineBlock && HealingMachineBlock.Companion.canSetSpawn(level)) {
|
||||
cir.setReturnValue(HealingMachineBlock.Companion.findStandUpPosition(EntityType.PLAYER, level, pos).map((vec3) -> ServerPlayer.RespawnPosAngle.of(vec3, pos)));
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "restoreFrom",
|
||||
at = @At("TAIL")
|
||||
)
|
||||
private void cobblemon$restoreCobblemonBag(ServerPlayer that, boolean keepEverything, CallbackInfo ci) {
|
||||
((BagEntity)(Object)this).cobblemon$setBagContainer(((BagEntity)that).cobblemon$getBagContainer());
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -69,7 +69,7 @@ public abstract class ClientRecipeBookMixin {
|
||||
value = "INVOKE",
|
||||
target = "Lcom/google/common/collect/ImmutableMap;copyOf(Ljava/util/Map;)Lcom/google/common/collect/ImmutableMap;"
|
||||
))
|
||||
private void addCustomAggregateCategories(Iterable<RecipeHolder<?>> recipes, RegistryAccess registryAccess, CallbackInfo ci, @Local(name = "map2") Map<RecipeBookCategories, List<RecipeCollection>> map2) {
|
||||
private void addCustomAggregateCategories(Iterable<RecipeHolder<?>> recipes, RegistryAccess registryAccess, CallbackInfo ci, @Local(ordinal = 1) Map<RecipeBookCategories, List<RecipeCollection>> map2) {
|
||||
CobblemonRecipeCategories.Companion.getCustomAggregateCategories().forEach((recipeBookCategories, list) -> map2.put(recipeBookCategories, (List) list.stream().flatMap((recipeBookCategoriesx) -> ((List) map2.getOrDefault(recipeBookCategoriesx, ImmutableList.of())).stream()).collect(ImmutableList.toImmutableList())));
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -20,14 +20,14 @@ import org.spongepowered.asm.mixin.injection.At;
|
||||
|
||||
@Mixin(RecipeBookComponent.class)
|
||||
public class RecipeBookComponentMixin {
|
||||
@Definition(id = "recipeBookCategories", local = @Local(name = "recipeBookCategories"))
|
||||
@Definition(id = "recipeBookCategories", local = @Local(type = RecipeBookCategories.class))
|
||||
@Definition(id = "FURNACE_SEARCH", field = "Lnet/minecraft/client/RecipeBookCategories;FURNACE_SEARCH:Lnet/minecraft/client/RecipeBookCategories;")
|
||||
@Expression("recipeBookCategories != FURNACE_SEARCH")
|
||||
@ModifyExpressionValue(
|
||||
method = "updateTabs",
|
||||
at = @At(value = "MIXINEXTRAS:EXPRESSION")
|
||||
)
|
||||
private boolean notCookingPotSearch(boolean original, @Local(name = "recipeBookCategories") RecipeBookCategories recipeBookCategories) {
|
||||
private boolean notCookingPotSearch(boolean original, @Local RecipeBookCategories recipeBookCategories) {
|
||||
return original && recipeBookCategories != CobblemonRecipeCategories.COOKING_POT_SEARCH.toVanillaCategory();
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@ import com.cobblemon.mod.common.client.pokedex.PokedexType
|
||||
import com.cobblemon.mod.common.entity.boat.CobblemonBoatType
|
||||
import com.cobblemon.mod.common.item.*
|
||||
import com.cobblemon.mod.common.item.armor.CobblemonArmorTrims
|
||||
import com.cobblemon.mod.common.item.bag.CobblemonBagItem
|
||||
import com.cobblemon.mod.common.item.battle.DireHitItem
|
||||
import com.cobblemon.mod.common.item.battle.GuardSpecItem
|
||||
import com.cobblemon.mod.common.item.battle.XStatItem
|
||||
@@ -1577,6 +1578,12 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val LUCIBELL = compostableBlockItem("lucibell", CobblemonBlocks.LUCIBELL, 0.85f)
|
||||
|
||||
//Bags
|
||||
@JvmField
|
||||
val TRAINER_BAG = this.create("trainer_bag", CobblemonBagItem())
|
||||
@JvmField
|
||||
val TRAINER_PACK = this.create("trainer_pack", CobblemonBagItem())
|
||||
|
||||
private fun blockItem(name: String, block: Block, rarity: Rarity = Rarity.COMMON): BlockItem = this.create(name, BlockItem(block, Item.Properties().rarity(rarity)))
|
||||
|
||||
private fun itemNameBlockItem(name: String, block: Block, rarity: Rarity = Rarity.COMMON): ItemNameBlockItem = this.create(name, ItemNameBlockItem(block, Item.Properties().rarity(rarity)))
|
||||
|
||||
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common
|
||||
|
||||
|
||||
import com.cobblemon.mod.common.block.campfirepot.CookingPotMenu
|
||||
import com.cobblemon.mod.common.item.bag.CobblemonBagMenu
|
||||
import com.cobblemon.mod.common.block.tmmachine.TMMachineMenu
|
||||
import com.cobblemon.mod.common.platform.PlatformRegistry
|
||||
import net.minecraft.core.Registry
|
||||
@@ -20,8 +21,9 @@ import net.minecraft.world.inventory.MenuType
|
||||
|
||||
object CobblemonMenuType : PlatformRegistry<Registry<MenuType<*>>, ResourceKey<Registry<MenuType<*>>>, MenuType<*>>() {
|
||||
|
||||
val COOKING_POT = MenuType.register("cooking_pot_menu", ::CookingPotMenu)
|
||||
val COOKING_POT = MenuType.register("cooking_pot", ::CookingPotMenu)
|
||||
val TM_MACHINE = MenuType.register("tm_machine_menu", ::TMMachineMenu)
|
||||
val COBBLEMON_BAG = MenuType.register("cobblemon_bag", ::CobblemonBagMenu)
|
||||
|
||||
override val registry: Registry<MenuType<*>>
|
||||
get() = BuiltInRegistries.MENU
|
||||
|
||||
@@ -13,6 +13,8 @@ import com.cobblemon.mod.common.client.net.OpenBehaviourEditorHandler
|
||||
import com.cobblemon.mod.common.client.net.PlayerInteractOptionsHandler
|
||||
import com.cobblemon.mod.common.client.net.SetClientPlayerDataHandler
|
||||
import com.cobblemon.mod.common.client.net.animation.PlayPosableAnimationHandler
|
||||
import com.cobblemon.mod.common.client.net.bag.UpdateBagMenuDataHandler
|
||||
import com.cobblemon.mod.common.client.net.bag.UseItemOnPokemonFromBagHandler
|
||||
import com.cobblemon.mod.common.client.net.battle.*
|
||||
import com.cobblemon.mod.common.client.net.callback.move.OpenMoveCallbackHandler
|
||||
import com.cobblemon.mod.common.client.net.callback.party.OpenPartyCallbackHandler
|
||||
@@ -76,6 +78,8 @@ import com.cobblemon.mod.common.net.messages.client.OpenBehaviourEditorPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.PlayerInteractOptionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.SetClientPlayerDataPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.animation.PlayPosableAnimationPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.bag.UpdateBagMenuDataPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.bag.UseItemOnPokemonFromBagPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.*
|
||||
import com.cobblemon.mod.common.net.messages.client.callback.OpenMoveCallbackPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.callback.OpenPartyCallbackPacket
|
||||
@@ -444,6 +448,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(BagCategoriesSyncPacket.ID, BagCategoriesSyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(TechnicalMachineRegistrySyncPacket.ID, TechnicalMachineRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
|
||||
// Effects
|
||||
@@ -640,6 +645,10 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(SetActiveTMPacket.ID, SetActiveTMPacket::decode, SetActiveTMPacketHandler))
|
||||
list.add(PacketRegisterInfo(SetTMMachineContainerDataPacket.ID, SetTMMachineContainerDataPacket::decode, SetTMMachineContainerDataPacketHandler))
|
||||
|
||||
// Bag
|
||||
list.add(PacketRegisterInfo(UpdateBagMenuDataPacket.ID, UpdateBagMenuDataPacket::decode, UpdateBagMenuDataHandler))
|
||||
list.add(PacketRegisterInfo(UseItemOnPokemonFromBagPacket.ID, UseItemOnPokemonFromBagPacket::decode, UseItemOnPokemonFromBagHandler))
|
||||
|
||||
// Behaviour Packets
|
||||
list.add(PacketRegisterInfo(SetEntityBehaviourPacket.ID, SetEntityBehaviourPacket::decode, SetEntityBehaviourHandler))
|
||||
list.add(PacketRegisterInfo(DamageOnCollisionPacket.ID, DamageOnCollisionPacket::decode, DamageOnCollisionPacketHandler))
|
||||
@@ -647,7 +656,7 @@ object CobblemonNetwork {
|
||||
// Habitat blocks
|
||||
list.add(PacketRegisterInfo(SaveHabitatBlockSettingsPacket.ID, SaveHabitatBlockSettingsPacket::decode, SaveHabitatBlockSettingsHandler))
|
||||
|
||||
// Debug / cheats
|
||||
// Debug
|
||||
list.add(PacketRegisterInfo(RequestOpenRidingStatsDebugGUIPacket.ID, RequestOpenRidingStatsDebugGUIPacket::decode, RequestOpenRidingStatsDebugGUIHandler))
|
||||
|
||||
|
||||
|
||||
@@ -321,6 +321,19 @@ object CobblemonSounds : PlatformRegistry<Registry<SoundEvent>, ResourceKey<Regi
|
||||
@JvmField
|
||||
val MEDICINAL_LEEK_PLACE = this.create("block.medicinal_leek.plant")
|
||||
|
||||
@JvmField
|
||||
val ITEM_BAG_OPEN = this.create("item.bag.open")
|
||||
@JvmField
|
||||
val ITEM_BAG_CLOSE = this.create("item.bag.close")
|
||||
@JvmField
|
||||
val ITEM_BAG_CLICK = this.create("item.bag.click")
|
||||
@JvmField
|
||||
val ITEM_BAG_ITEM_IN = this.create("item.bag.item_in")
|
||||
@JvmField
|
||||
val ITEM_BAG_ITEM_OUT = this.create("item.bag.item_out")
|
||||
@JvmField
|
||||
val ITEM_BAG_EQUIP = this.create("item.bag.equip")
|
||||
|
||||
@JvmField
|
||||
val GILDED_CHEST_OPEN = this.create("block.gilded_chest.open")
|
||||
@JvmField
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.bag
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.data.JsonDataRegistry
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.net.messages.client.data.BagCategoriesSyncPacket
|
||||
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.TagKeyAdapter
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.packs.PackType
|
||||
import net.minecraft.tags.TagKey
|
||||
import net.minecraft.world.item.Item
|
||||
|
||||
object BagCategories: JsonDataRegistry<BagCategory> {
|
||||
|
||||
override val id: ResourceLocation = cobblemonResource("bag_categories")
|
||||
override val type: PackType = PackType.SERVER_DATA
|
||||
override val observable = SimpleObservable<BagCategories>()
|
||||
|
||||
override val gson = GsonBuilder()
|
||||
.disableHtmlEscaping()
|
||||
.setPrettyPrinting()
|
||||
.registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter)
|
||||
.registerTypeAdapter(TypeToken.getParameterized(TagKey::class.java, Item::class.java).type, TagKeyAdapter(Registries.ITEM))
|
||||
.create()
|
||||
|
||||
override val typeToken: TypeToken<BagCategory> = TypeToken.get(BagCategory::class.java)
|
||||
override val resourcePath = "bag_categories"
|
||||
|
||||
private val bagCategories = hashMapOf<ResourceLocation, BagCategory>()
|
||||
|
||||
override fun reload(data: Map<ResourceLocation, BagCategory>) {
|
||||
bagCategories.clear()
|
||||
data.forEach { identifier, category ->
|
||||
try {
|
||||
category.identifier = identifier
|
||||
bagCategories[identifier] = category
|
||||
} catch (e: Exception) {
|
||||
Cobblemon.LOGGER.error("Skipped loading the {} category", identifier, e)
|
||||
}
|
||||
}
|
||||
Cobblemon.LOGGER.info("Loaded {} bag categories", bagCategories.size)
|
||||
this.observable.emit(this)
|
||||
}
|
||||
|
||||
override fun sync(player: ServerPlayer) {
|
||||
BagCategoriesSyncPacket(bagCategories.values.toList())
|
||||
}
|
||||
|
||||
fun getOrderedCategoriesList(): List<BagCategory> {
|
||||
return bagCategories.values.toList().sortedBy { it.order }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.bag
|
||||
|
||||
import com.cobblemon.mod.common.util.readIdentifier
|
||||
import com.cobblemon.mod.common.util.writeIdentifier
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.tags.TagKey
|
||||
import net.minecraft.util.StringRepresentable
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.ItemStack
|
||||
|
||||
class BagCategory(
|
||||
identifier: ResourceLocation,
|
||||
val order: Int,
|
||||
val icon: ResourceLocation,
|
||||
val whiteListTag: TagKey<Item>,
|
||||
val blackListTag: TagKey<Item>,
|
||||
val maxCount: Int
|
||||
): StringRepresentable {
|
||||
@Transient
|
||||
var identifier: ResourceLocation = identifier
|
||||
internal set
|
||||
|
||||
override fun getSerializedName(): String = identifier.toString()
|
||||
|
||||
fun getName(): MutableComponent = Component.translatable("${identifier.namespace}.bag_category.${identifier.path}")
|
||||
|
||||
fun itemIsValid(itemStack: ItemStack): Boolean {
|
||||
if (itemStack.`is`(blackListTag)) return false
|
||||
if (itemStack.`is`(whiteListTag)) return true
|
||||
return false
|
||||
}
|
||||
|
||||
fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeIdentifier(identifier)
|
||||
buffer.writeInt(order)
|
||||
buffer.writeIdentifier(icon)
|
||||
buffer.writeIdentifier(whiteListTag.location)
|
||||
buffer.writeIdentifier(blackListTag.location)
|
||||
buffer.writeInt(maxCount)
|
||||
}
|
||||
|
||||
companion object {
|
||||
internal fun decode(buffer: RegistryFriendlyByteBuf): BagCategory {
|
||||
return BagCategory(
|
||||
buffer.readIdentifier(),
|
||||
buffer.readInt(),
|
||||
buffer.readIdentifier(),
|
||||
TagKey.create(Registries.ITEM, buffer.readIdentifier()),
|
||||
TagKey.create(Registries.ITEM, buffer.readIdentifier()),
|
||||
buffer.readInt()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -239,6 +239,10 @@ open class PokemonBattle(
|
||||
}
|
||||
|
||||
fun writeShowdownAction(vararg messages: String) {
|
||||
if (messages.any { it.contains("\n") || it.contains("\r") }) {
|
||||
LOGGER.warn("Refusing to forward Showdown action with an embedded line break for battle {}: {}", battleId, messages.joinToString(" | "))
|
||||
return
|
||||
}
|
||||
log(messages.joinToString("\n"))
|
||||
ShowdownService.service.send(battleId, messages.toList().toTypedArray())
|
||||
}
|
||||
|
||||
@@ -9,12 +9,14 @@
|
||||
package com.cobblemon.mod.common.api.events.pokemon
|
||||
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.cobblemon.mod.common.api.events.Cancelable
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.moLangFunctionMap
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.trade.TradeParticipant
|
||||
import com.cobblemon.mod.common.util.asArrayValue
|
||||
import com.cobblemon.mod.common.util.getPlayer
|
||||
|
||||
/**
|
||||
@@ -31,9 +33,9 @@ interface TradeEvent {
|
||||
val tradeParticipant1: TradeParticipant
|
||||
|
||||
/**
|
||||
* The [Pokemon] being traded by the first participant.
|
||||
* All the [Pokemon] the first participant receives in the trade.
|
||||
*/
|
||||
val tradeParticipant1Pokemon: Pokemon
|
||||
val tradeParticipant1Pokemon: List<Pokemon>
|
||||
|
||||
/**
|
||||
* The second [TradeParticipant].
|
||||
@@ -41,9 +43,19 @@ interface TradeEvent {
|
||||
val tradeParticipant2: TradeParticipant
|
||||
|
||||
/**
|
||||
* The [Pokemon] being traded by the second participant.
|
||||
* All the [Pokemon] the second participant receives in the trade.
|
||||
*/
|
||||
val tradeParticipant2Pokemon: Pokemon
|
||||
val tradeParticipant2Pokemon: List<Pokemon>
|
||||
|
||||
fun createContext(): MutableMap<String, MoValue> = mutableMapOf(
|
||||
"trade_participant_1" to (tradeParticipant1.uuid.getPlayer()?.asMoLangValue() ?: DoubleValue.ZERO),
|
||||
"trade_participant_2" to (tradeParticipant2.uuid.getPlayer()?.asMoLangValue() ?: DoubleValue.ZERO),
|
||||
// Kept for backwards compatibility, this is the first Pokémon of each side.
|
||||
"trade_participant_1_pokemon" to tradeParticipant1Pokemon.first().struct,
|
||||
"trade_participant_2_pokemon" to tradeParticipant2Pokemon.first().struct,
|
||||
"trade_participant_1_pokemon_list" to tradeParticipant1Pokemon.asArrayValue { it.struct },
|
||||
"trade_participant_2_pokemon_list" to tradeParticipant2Pokemon.asArrayValue { it.struct }
|
||||
)
|
||||
|
||||
/**
|
||||
* Event fired when a trade is about to happen. Cancelling this event prevents the trade from occurring.
|
||||
@@ -53,16 +65,11 @@ interface TradeEvent {
|
||||
*/
|
||||
data class Pre(
|
||||
override val tradeParticipant1: TradeParticipant,
|
||||
override val tradeParticipant1Pokemon: Pokemon,
|
||||
override val tradeParticipant1Pokemon: List<Pokemon>,
|
||||
override val tradeParticipant2: TradeParticipant,
|
||||
override val tradeParticipant2Pokemon: Pokemon
|
||||
override val tradeParticipant2Pokemon: List<Pokemon>
|
||||
) : TradeEvent, Cancelable() {
|
||||
val context = mutableMapOf(
|
||||
"trade_participant_1" to (tradeParticipant1.uuid.getPlayer()?.asMoLangValue() ?: DoubleValue.ZERO),
|
||||
"trade_participant_2" to (tradeParticipant2.uuid.getPlayer()?.asMoLangValue() ?: DoubleValue.ZERO),
|
||||
"trade_participant_1_pokemon" to tradeParticipant1Pokemon.struct,
|
||||
"trade_participant_2_pokemon" to tradeParticipant2Pokemon.struct
|
||||
)
|
||||
val context = createContext()
|
||||
|
||||
val functions = moLangFunctionMap(
|
||||
cancelFunc
|
||||
@@ -77,15 +84,10 @@ interface TradeEvent {
|
||||
*/
|
||||
data class Post(
|
||||
override val tradeParticipant1: TradeParticipant,
|
||||
override val tradeParticipant1Pokemon: Pokemon,
|
||||
override val tradeParticipant1Pokemon: List<Pokemon>,
|
||||
override val tradeParticipant2: TradeParticipant,
|
||||
override val tradeParticipant2Pokemon: Pokemon
|
||||
override val tradeParticipant2Pokemon: List<Pokemon>
|
||||
) : TradeEvent {
|
||||
val context = mutableMapOf(
|
||||
"trade_participant_1" to (tradeParticipant1.uuid.getPlayer()?.asMoLangValue() ?: DoubleValue.ZERO),
|
||||
"trade_participant_2" to (tradeParticipant2.uuid.getPlayer()?.asMoLangValue() ?: DoubleValue.ZERO),
|
||||
"trade_participant_1_pokemon" to tradeParticipant1Pokemon.struct,
|
||||
"trade_participant_2_pokemon" to tradeParticipant2Pokemon.struct
|
||||
)
|
||||
val context = createContext()
|
||||
}
|
||||
}
|
||||
@@ -198,7 +198,17 @@ interface Spawner {
|
||||
val mid = chunk.getBlockState(startPos)
|
||||
val above = chunk.getBlockState(abovePos)
|
||||
|
||||
return above.isPathfindable(PathComputationType.AIR) && mid.isAir
|
||||
// Above must be non-solid
|
||||
if (!above.isPathfindable(PathComputationType.AIR)) {
|
||||
return false
|
||||
}
|
||||
|
||||
// Position must be non-air
|
||||
if (mid.isAir) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
fun constrainArea(area: SpawningZoneInput): SpawningZoneInput? {
|
||||
|
||||
@@ -140,6 +140,20 @@ object CobblemonItemTags {
|
||||
@JvmField val WEARABLE_HAT_ITEMS = create("held/visibility/hat")
|
||||
@JvmField val HIDDEN_ITEMS = create("held/visibility/hidden")
|
||||
|
||||
//Bag Categories Tags
|
||||
@JvmField val BAG_WHITELIST_POKE_BALLS = create("bag/whitelist_poke_balls")
|
||||
@JvmField val BAG_BLACKLIST_POKE_BALLS = create("bag/blacklist_poke_balls")
|
||||
@JvmField val BAG_WHITELIST_CONSUMABLES = create("bag/whitelist_consumables")
|
||||
@JvmField val BAG_BLACKLIST_CONSUMABLES = create("bag/blacklist_consumables")
|
||||
@JvmField val BAG_WHITELIST_BERRIES = create("bag/whitelist_berries")
|
||||
@JvmField val BAG_BLACKLIST_BERRIES = create("bag/blacklist_berries")
|
||||
@JvmField val BAG_WHITELIST_HELD_EVO = create("bag/whitelist_held_evo")
|
||||
@JvmField val BAG_BLACKLIST_HELD_EVO = create("bag/blacklist_held_evo")
|
||||
@JvmField val BAG_WHITELIST_CURRENCY = create("bag/whitelist_currency")
|
||||
@JvmField val BAG_BLACKLIST_CURRENCY = create("bag/blacklist_currency")
|
||||
@JvmField val BAG_WHITELIST_TMS = create("bag/whitelist_tms")
|
||||
@JvmField val BAG_BLACKLIST_TMS = create("bag/blacklist_tms")
|
||||
|
||||
//Empty Tag
|
||||
@JvmField val EMPTY = create("empty")
|
||||
|
||||
|
||||
@@ -117,6 +117,9 @@ abstract class ShowdownActionResponse(val type: ShowdownActionResponseType) {
|
||||
|
||||
data class MoveActionResponse(var moveName: String, var targetPnx: String? = null, var gimmickID: String? = null): ShowdownActionResponse(ShowdownActionResponseType.MOVE) {
|
||||
override fun isValid(activeBattlePokemon: ActiveBattlePokemon, showdownMoveSet: ShowdownMoveset?, forceSwitch: Boolean): Boolean {
|
||||
// Ensure that the gimmick ID the player is sending is valid
|
||||
gimmickID?.let { if (it !in VALID_GIMMICK_IDS) return false }
|
||||
|
||||
if (forceSwitch || showdownMoveSet == null) {
|
||||
return false
|
||||
}
|
||||
@@ -168,6 +171,10 @@ data class MoveActionResponse(var moveName: String, var targetPnx: String? = nul
|
||||
gimmickID = buffer.readNullable { buffer.readString() }
|
||||
return this
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val VALID_GIMMICK_IDS = ShowdownMoveset.Gimmick.entries.map { it.id }.toSet()
|
||||
}
|
||||
}
|
||||
|
||||
data class HealItemActionResponse(var item: String) : ShowdownActionResponse(ShowdownActionResponseType.FORCE_PASS) {
|
||||
@@ -183,7 +190,8 @@ data class HealItemActionResponse(var item: String) : ShowdownActionResponse(Sho
|
||||
}
|
||||
|
||||
override fun isValid(activeBattlePokemon: ActiveBattlePokemon, showdownMoveSet: ShowdownMoveset?, forceSwitch: Boolean): Boolean {
|
||||
return !forceSwitch
|
||||
// Previously checked for !forceSwitch, excepts in the case of a forceSwitch, this couldn't legally be sent anyway.
|
||||
return false
|
||||
}
|
||||
|
||||
override fun toShowdownString(activeBattlePokemon: ActiveBattlePokemon, showdownMoveSet: ShowdownMoveset?): String {
|
||||
|
||||
+11
-2
@@ -37,7 +37,6 @@ import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.cobblemon.mod.common.util.battleLang
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
|
||||
/**
|
||||
* Format: |move|POKEMON|MOVE|TARGET
|
||||
@@ -77,7 +76,7 @@ class MoveInstruction(
|
||||
val pokemonName = userPokemon.getName()
|
||||
ShowdownInterpreter.lastCauser[battle.battleId] = message
|
||||
// For Spread targets the message data only gives the pnx strings. So we can't know what pokemon are actually targeted until the previous messages have been interpreted
|
||||
val spreadTargetPokemon = spreadTargets.map { battle.activePokemon.firstOrNull() { poke -> poke.getPNX() == it }?.battlePokemon }
|
||||
val spreadTargetPokemon = spreadTargets.map { battle.activePokemon.firstOrNull { poke -> poke.getPNX() == it }?.battlePokemon }
|
||||
|
||||
val targetPokemonEntity = targetPokemon?.entity
|
||||
if (targetPokemonEntity != null) {
|
||||
@@ -137,10 +136,20 @@ class MoveInstruction(
|
||||
|
||||
val subsequentInstructions = instructionSet.findInstructionsCausedBy(this)
|
||||
val missedTargets = subsequentInstructions.filterIsInstance<MissInstruction>().mapNotNull { it.target }
|
||||
val faintedTargets = subsequentInstructions.filterIsInstance<FaintInstruction>().map { it.faintingPokemon }
|
||||
val failed = subsequentInstructions.any { it is FailInstruction }
|
||||
val failedTargets = subsequentInstructions.filterIsInstance<FailInstruction>().mapNotNull { it.target }
|
||||
val hitCountInstruction = subsequentInstructions.filterIsInstance<HitCountInstruction>().firstOrNull()
|
||||
|
||||
runtime.environment.query.addFunction("target_fainted") { params ->
|
||||
if (params.params.size == 0) {
|
||||
return@addFunction DoubleValue(faintedTargets.isNotEmpty())
|
||||
} else {
|
||||
val entityUUID = params.getString(0)
|
||||
return@addFunction DoubleValue(faintedTargets.any { it.entity?.stringUUID == entityUUID })
|
||||
}
|
||||
}
|
||||
|
||||
runtime.environment.query.addFunction("missed") { params ->
|
||||
if (params.params.size == 0) {
|
||||
return@addFunction DoubleValue(missedTargets.isNotEmpty())
|
||||
|
||||
@@ -24,6 +24,7 @@ import net.minecraft.network.chat.Component
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.util.RandomSource
|
||||
import net.minecraft.world.InteractionResult
|
||||
import net.minecraft.world.entity.EntityType
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.Item
|
||||
@@ -31,13 +32,9 @@ import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.TooltipFlag
|
||||
import net.minecraft.world.item.context.BlockPlaceContext
|
||||
import net.minecraft.world.level.BlockGetter
|
||||
import net.minecraft.world.level.CollisionGetter
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.block.BaseEntityBlock
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.HorizontalDirectionalBlock
|
||||
import net.minecraft.world.level.block.Mirror
|
||||
import net.minecraft.world.level.block.RenderShape
|
||||
import net.minecraft.world.level.block.Rotation
|
||||
import net.minecraft.world.level.block.*
|
||||
import net.minecraft.world.level.block.entity.BlockEntity
|
||||
import net.minecraft.world.level.block.entity.BlockEntityTicker
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType
|
||||
@@ -48,9 +45,11 @@ import net.minecraft.world.level.block.state.properties.IntegerProperty
|
||||
import net.minecraft.world.level.block.state.properties.Property
|
||||
import net.minecraft.world.level.pathfinder.PathComputationType
|
||||
import net.minecraft.world.phys.BlockHitResult
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import net.minecraft.world.phys.shapes.CollisionContext
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
import net.minecraft.world.phys.shapes.VoxelShape
|
||||
import java.util.Optional
|
||||
|
||||
@Suppress("DEPRECATED", "OVERRIDE_DEPRECATION")
|
||||
class HealingMachineBlock(settings: Properties) : BaseEntityBlock(settings) {
|
||||
@@ -79,6 +78,14 @@ class HealingMachineBlock(settings: Properties) : BaseEntityBlock(settings) {
|
||||
const val MAX_CHARGE_LEVEL = 5
|
||||
val CHARGE_LEVEL: IntegerProperty = IntegerProperty.create("charge", 0, MAX_CHARGE_LEVEL + 1)
|
||||
val NATURAL: BooleanProperty = BooleanProperty.create("natural")
|
||||
|
||||
fun canSetSpawn(level: Level): Boolean {
|
||||
return level.gameRules.getBoolean(CobblemonGameRules.HEALER_SET_SPAWN)
|
||||
}
|
||||
|
||||
fun findStandUpPosition(entityType: EntityType<*>, level: CollisionGetter, pos: BlockPos): Optional<Vec3> {
|
||||
return RespawnAnchorBlock.findStandUpPosition(entityType, level, pos) // Exists if we ever want to make something more custom, but anchor block logic should suffice
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
@@ -158,7 +165,12 @@ class HealingMachineBlock(settings: Properties) : BaseEntityBlock(settings) {
|
||||
}
|
||||
val party = serverPlayerEntity.party()
|
||||
val pc = serverPlayerEntity.pc()
|
||||
val healPC = player.level().gameRules.getBoolean(CobblemonGameRules.HEALERS_HEAL_PC);
|
||||
val healPC = player.level().gameRules.getBoolean(CobblemonGameRules.HEALERS_HEAL_PC)
|
||||
|
||||
// Do spawnpoint stuff
|
||||
if (canSetSpawn(world)) {
|
||||
player.setRespawnPosition(world.dimension(), blockPos, player.yRot, false, true)
|
||||
}
|
||||
|
||||
if (party.none() && (!healPC || pc.none())) {
|
||||
player.sendSystemMessage(lang("healingmachine.nopokemon").red(), true)
|
||||
@@ -183,6 +195,7 @@ class HealingMachineBlock(settings: Properties) : BaseEntityBlock(settings) {
|
||||
player.sendSystemMessage(lang("healingmachine.notenoughcharge", "${((neededCharge/party.count())*100f).toInt()}%").red(), true)
|
||||
}
|
||||
party.forEach { it.tryRecallWithAnimation() }
|
||||
|
||||
return InteractionResult.CONSUME
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ class OrbBlock(properties: Properties) : SixFaceRotationalBlock(properties) {
|
||||
|
||||
val FLOOR_NORTH = Shapes.box(0.3125, 0.0, 0.3125, 0.6875, 0.375, 0.6875)
|
||||
val WALL_NORTH = Shapes.box(0.3125, 0.3125, 0.625, 0.6875, 0.6875, 1.0)
|
||||
val CEILING_NORTH = Shapes.box(0.3125, 0.625, 0.375, 0.6875, 1.0, 0.6875)
|
||||
val CEILING_NORTH = Shapes.box(0.3125, 0.625, 0.3125, 0.6875, 1.0, 0.6875)
|
||||
}
|
||||
|
||||
init {
|
||||
|
||||
@@ -160,8 +160,8 @@ class TypeGemClusterBlock(
|
||||
&& state.getValue(STAGE) == 3) return false
|
||||
|
||||
val supportPos = pos.relative(state.getValue(FACING).opposite)
|
||||
val supportBlock = level.getBlockState(supportPos).block
|
||||
return CobblemonBlocks.typeGemBlocks().containsValue(supportBlock) || (supportBlock == CobblemonBlocks.TYPE_GEM_CORE) // Cannot grow if not on any gem blocks
|
||||
val supportState = level.getBlockState(supportPos)
|
||||
return supportState.`is`(CobblemonBlockTags.TYPE_GEM_BLOCKS) || supportState.block == CobblemonBlocks.TYPE_GEM_CORE // Cannot grow if not on any gem blocks
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -51,10 +51,20 @@ class TypeGemCoreBlock(properties: Properties) : Block(properties) {
|
||||
ResourceLocation.parse("cobblemon:dragon_gem_block") to CobblemonBlocks.TYPE_GEM_CLUSTER_DRAGON,
|
||||
ResourceLocation.parse("cobblemon:dark_gem_block") to CobblemonBlocks.TYPE_GEM_CLUSTER_DARK,
|
||||
ResourceLocation.parse("cobblemon:steel_gem_block") to CobblemonBlocks.TYPE_GEM_CLUSTER_STEEL,
|
||||
ResourceLocation.parse("cobblemon:fairy_gem_block") to CobblemonBlocks.TYPE_GEM_CLUSTER_FAIRY
|
||||
ResourceLocation.parse("cobblemon:fairy_gem_block") to CobblemonBlocks.TYPE_GEM_CLUSTER_FAIRY,
|
||||
ResourceLocation.parse("minecraft:amethyst_block") to Blocks.SMALL_AMETHYST_BUD
|
||||
)
|
||||
}
|
||||
|
||||
val AMETHYST_STAGES = listOf(
|
||||
Blocks.SMALL_AMETHYST_BUD,
|
||||
Blocks.MEDIUM_AMETHYST_BUD,
|
||||
Blocks.LARGE_AMETHYST_BUD,
|
||||
Blocks.AMETHYST_CLUSTER
|
||||
)
|
||||
|
||||
private fun isAmethystStage(block: Block) = block in AMETHYST_STAGES
|
||||
|
||||
fun getConnectedGemBlocks(level: BlockGetter, pos: BlockPos): List<Pair<BlockState, BlockPos>> {
|
||||
val connectedGems = mutableListOf<Pair<BlockState, BlockPos>>()
|
||||
val visited = mutableSetOf<BlockPos>()
|
||||
@@ -85,12 +95,16 @@ class TypeGemCoreBlock(properties: Properties) : Block(properties) {
|
||||
Direction.entries.forEach {
|
||||
if (random.nextFloat() < Cobblemon.config.typeGemGrowthChance) {
|
||||
val faceState = level.getBlockState(pos.relative(it))
|
||||
val randomGrowthType = decideClusterGrowthType(level, pos)
|
||||
val newState = BLOCK_TO_CLUSTER[BuiltInRegistries.BLOCK.getKey(state.block)]?.defaultBlockState()
|
||||
var newState = BLOCK_TO_CLUSTER[BuiltInRegistries.BLOCK.getKey(state.block)]?.defaultBlockState()
|
||||
?.setValue(DirectionalBlock.FACING, it)
|
||||
?.setValue(GROWTH_TYPE, randomGrowthType)
|
||||
?: return
|
||||
|
||||
if (newState.hasProperty(GROWTH_TYPE)) {
|
||||
newState = newState.setValue(GROWTH_TYPE, decideClusterGrowthType(level, pos))
|
||||
} else if (getConnectedGemBlocks(level, pos).size > Cobblemon.config.typeGemMaxConnected) {
|
||||
return@forEach
|
||||
}
|
||||
|
||||
if (faceState.`is`(Blocks.AIR)) {
|
||||
level.setBlock(pos.relative(it), newState, 3)
|
||||
}
|
||||
@@ -132,7 +146,7 @@ class TypeGemCoreBlock(properties: Properties) : Block(properties) {
|
||||
if (!visited.add(clusterPos)) continue
|
||||
|
||||
val clusterState = level.getBlockState(clusterPos)
|
||||
if (clusterState.block == expectedCluster) {
|
||||
if (clusterState.block == expectedCluster && clusterState.hasProperty(GROWTH_TYPE)) {
|
||||
clusters += clusterState to clusterPos
|
||||
}
|
||||
}
|
||||
@@ -178,13 +192,41 @@ class TypeGemCoreBlock(properties: Properties) : Block(properties) {
|
||||
Direction.entries.forEach { direction ->
|
||||
val relativePos = pos.relative(direction)
|
||||
val relativeState = level.getBlockState(relativePos)
|
||||
val clusterBlock = relativeState.block as? TypeGemClusterBlock ?: return@forEach
|
||||
|
||||
if ((relativeState.getValue(DirectionalBlock.FACING) == direction &&
|
||||
random.nextFloat() < Cobblemon.config.typeGemGrowthChance) || forceGrow
|
||||
) {
|
||||
clusterBlock.advanceGrowth(relativeState, level, relativePos, random)
|
||||
val matchesFace = relativeState.hasProperty(DirectionalBlock.FACING)
|
||||
&& relativeState.getValue(DirectionalBlock.FACING) == direction
|
||||
if (!(forceGrow || (matchesFace && random.nextFloat() < Cobblemon.config.typeGemGrowthChance))) {
|
||||
return@forEach
|
||||
}
|
||||
|
||||
val block = relativeState.block
|
||||
if (block is TypeGemClusterBlock) {
|
||||
block.advanceGrowth(relativeState, level, relativePos, random)
|
||||
} else if (isAmethystStage(block)) {
|
||||
advanceAmethyst(relativeState, level, relativePos)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun advanceAmethyst(state: BlockState, level: LevelAccessor, pos: BlockPos) {
|
||||
val facing = state.getValue(DirectionalBlock.FACING)
|
||||
val supportState = level.getBlockState(pos.relative(facing.opposite))
|
||||
if (!supportState.`is`(CobblemonBlockTags.TYPE_GEM_BLOCKS) && supportState.block != CobblemonBlocks.TYPE_GEM_CORE) {
|
||||
return
|
||||
}
|
||||
|
||||
if (state.block != Blocks.AMETHYST_CLUSTER) {
|
||||
val nextStage = AMETHYST_STAGES[AMETHYST_STAGES.indexOf(state.block) + 1]
|
||||
level.setBlock(pos, nextStage.defaultBlockState().setValue(DirectionalBlock.FACING, facing), 3)
|
||||
return
|
||||
}
|
||||
|
||||
// Fully grown clusters mature into amethyst blocks unless boxed in, mirroring stunted type gems
|
||||
val boxedIn = Direction.entries.any { direction ->
|
||||
direction != facing.opposite
|
||||
&& level.getBlockState(pos.relative(direction)).`is`(CobblemonBlockTags.TYPE_GEM_BLOCKS)
|
||||
}
|
||||
if (!boxedIn) {
|
||||
level.setBlock(pos, Blocks.AMETHYST_BLOCK.defaultBlockState(), 3)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,10 +9,13 @@
|
||||
package com.cobblemon.mod.common.client
|
||||
|
||||
import com.cobblemon.mod.common.BakingOverride
|
||||
import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.item.bag.CobblemonBagItem
|
||||
import com.cobblemon.mod.common.util.cobblemonModel
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.resources.model.ModelResourceLocation
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.item.Item
|
||||
|
||||
/**
|
||||
* The purpose of this class is to hold models that we want baked, but aren't associated with
|
||||
@@ -103,9 +106,33 @@ object CobblemonBakingOverrides {
|
||||
cobblemonModel("surprise_mulch", "none")
|
||||
)
|
||||
|
||||
// Bag
|
||||
val bagModels = mutableMapOf<CobblemonBagItem, BakingOverride>()
|
||||
val TRAINER_PACK = registerBagOverride(
|
||||
CobblemonItems.TRAINER_PACK,
|
||||
cobblemonResource("item/bag/trainer_pack"),
|
||||
cobblemonModel("trainer_pack", "none")
|
||||
)
|
||||
val TRAINER_BAG = registerBagOverride(
|
||||
CobblemonItems.TRAINER_BAG,
|
||||
cobblemonResource("item/bag/trainer_bag"),
|
||||
cobblemonModel("trainer_bag", "none")
|
||||
)
|
||||
/*val BAG_PENNY = registerBagOverride(
|
||||
CobblemonItems.TRAINER_PACK,
|
||||
cobblemonResource("item/bag/bag_penny"),
|
||||
cobblemonModel("bag_penny", "penny")
|
||||
)*/
|
||||
|
||||
fun registerOverride(modelLocation: ResourceLocation, modelIdentifier: ModelResourceLocation): BakingOverride {
|
||||
val result = BakingOverride(modelLocation, modelIdentifier)
|
||||
models.add(result)
|
||||
return result
|
||||
}
|
||||
|
||||
fun registerBagOverride(associatedItem: CobblemonBagItem, modelLocation: ResourceLocation, modelIdentifier: ModelResourceLocation): BakingOverride {
|
||||
val result = registerOverride(modelLocation, modelIdentifier)
|
||||
bagModels[associatedItem] = result
|
||||
return result
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ import com.cobblemon.mod.common.client.battle.ClientBattle
|
||||
import com.cobblemon.mod.common.client.gui.PartyOverlay
|
||||
import com.cobblemon.mod.common.client.gui.PartyOverlayDataControl
|
||||
import com.cobblemon.mod.common.client.gui.RideControlsOverlay
|
||||
import com.cobblemon.mod.common.client.gui.bag.CobblemonBagScreen
|
||||
import com.cobblemon.mod.common.client.gui.battle.BattleOverlay
|
||||
import com.cobblemon.mod.common.client.gui.cookingpot.CookingPotScreen
|
||||
import com.cobblemon.mod.common.client.gui.party.PartyTutorialToasts
|
||||
@@ -46,6 +47,7 @@ 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.CobblemonBagRenderer
|
||||
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
|
||||
@@ -391,7 +393,7 @@ object CobblemonClient {
|
||||
CobblemonBlocks.X_SP_ATK,
|
||||
CobblemonBlocks.X_SP_DEF,
|
||||
CobblemonBlocks.X_SPEED,
|
||||
CobblemonBlocks.TM_MACHINE,
|
||||
CobblemonBlocks.TM_MACHINE,
|
||||
|
||||
CobblemonBlocks.GALARICA_CUFF,
|
||||
CobblemonBlocks.GALARICA_WREATH,
|
||||
@@ -419,7 +421,7 @@ object CobblemonClient {
|
||||
CobblemonBlocks.MOOMOO_MILK,
|
||||
CobblemonBlocks.MEDICINAL_BREW,
|
||||
CobblemonBlocks.TERRAIN_EXTENDER,
|
||||
|
||||
|
||||
CobblemonBlocks.RED_MINT_LEAF_LITTER,
|
||||
CobblemonBlocks.POTTED_RED_MINT,
|
||||
CobblemonBlocks.BLUE_MINT_LEAF_LITTER,
|
||||
@@ -539,14 +541,17 @@ object CobblemonClient {
|
||||
skinMap?.get(PlayerSkin.Model.WIDE) as LivingEntityRenderer<Player, PlayerModel<Player>>
|
||||
renderer?.addLayer(PokemonOnShoulderRenderer(renderer))
|
||||
renderer?.addLayer(PlayerRecallBallRenderer(renderer))
|
||||
renderer?.addLayer(CobblemonBagRenderer(renderer))
|
||||
renderer = skinMap[PlayerSkin.Model.SLIM] as LivingEntityRenderer<Player, PlayerModel<Player>>?
|
||||
renderer?.addLayer(PokemonOnShoulderRenderer(renderer))
|
||||
renderer?.addLayer(PlayerRecallBallRenderer(renderer))
|
||||
renderer?.addLayer(CobblemonBagRenderer(renderer))
|
||||
}
|
||||
|
||||
private fun registerMenuScreens() {
|
||||
MenuScreens.register(CobblemonMenuType.COOKING_POT, ::CookingPotScreen)
|
||||
MenuScreens.register(CobblemonMenuType.TM_MACHINE, ::TMMachineScreen)
|
||||
MenuScreens.register(CobblemonMenuType.COBBLEMON_BAG, ::CobblemonBagScreen)
|
||||
}
|
||||
|
||||
private fun registerBlockEntityRenderers() {
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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.bag
|
||||
|
||||
import com.cobblemon.mod.common.api.bag.BagCategories
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.render.getDepletableRedGreen
|
||||
import com.cobblemon.mod.common.util.asTranslated
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.Button
|
||||
import net.minecraft.client.sounds.SoundManager
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
class BagCategoryButton(
|
||||
x: Int,
|
||||
y: Int,
|
||||
val parent: CobblemonBagScreen,
|
||||
val category: Int,
|
||||
val action: OnPress
|
||||
): Button(x, y, WIDTH, HEIGHT, Component.empty(), action, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
companion object {
|
||||
private const val WIDTH = 32
|
||||
private const val HEIGHT = 31
|
||||
|
||||
private val CATEGORY_SLOT = cobblemonResource("textures/gui/bag/bag_tab.png")
|
||||
private val VOLUME_BAR = cobblemonResource("textures/gui/bag/bag_tab_volume_bar.png")
|
||||
}
|
||||
|
||||
override fun renderWidget(context: GuiGraphics, mouseX: Int, mouseY: Int, partialTick: Float) {
|
||||
val orderedCategories = BagCategories.getOrderedCategoriesList()
|
||||
|
||||
blitk(
|
||||
matrixStack = context.pose(),
|
||||
texture = CATEGORY_SLOT,
|
||||
x = x, y = y,
|
||||
width = WIDTH, height = HEIGHT,
|
||||
textureHeight = 64,
|
||||
vOffset = if (parent.menu.currentlySelectedCategory == category) 32 else 0
|
||||
)
|
||||
|
||||
blitk(
|
||||
matrixStack = context.pose(),
|
||||
texture = if (category == -1) ResourceLocation("minecraft", "textures/item/bundle.png") else orderedCategories[category].icon,
|
||||
x = x + 8, y = y + 9,
|
||||
width = 16, height = 16
|
||||
)
|
||||
|
||||
//The Bar
|
||||
if (category != -1) {
|
||||
blitk(
|
||||
matrixStack = context.pose(),
|
||||
texture = VOLUME_BAR,
|
||||
x = x + 8, y = y + 25,
|
||||
width = 16, height = 3
|
||||
)
|
||||
|
||||
val itemRatio = (parent.menu.categoryItemCounts[category].toFloat() / orderedCategories[category].maxCount).coerceIn(0F, 1F)
|
||||
val barWidth = itemRatio * 14
|
||||
val (red, green) = getDepletableRedGreen(1 - itemRatio)
|
||||
|
||||
blitk(
|
||||
matrixStack = context.pose(),
|
||||
texture = CobblemonResources.WHITE,
|
||||
x = x + 9, y = y + 26,
|
||||
width = barWidth, height = 1,
|
||||
red = red * 0.8F, green = green * 0.8F, blue = 0.27F
|
||||
)
|
||||
}
|
||||
|
||||
if (isHovered) {
|
||||
context.renderTooltip(Minecraft.getInstance().font, if (category == -1) lang("bag_categories.all_items") else orderedCategories[category].getName(), mouseX, mouseY)
|
||||
}
|
||||
}
|
||||
|
||||
override fun playDownSound(handler: SoundManager) {}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.bag
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.Button
|
||||
import net.minecraft.client.sounds.SoundManager
|
||||
import net.minecraft.network.chat.Component
|
||||
|
||||
class BagCategoryPageButton(
|
||||
x: Int,
|
||||
y: Int,
|
||||
val parent: CobblemonBagScreen,
|
||||
val leftButton: Boolean,
|
||||
val action: OnPress
|
||||
): Button(x, y, WIDTH, HEIGHT, Component.empty(), action, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
companion object {
|
||||
private const val WIDTH = 12
|
||||
private const val HEIGHT = 10
|
||||
|
||||
private val LEFT_BUTTON = cobblemonResource("textures/gui/bag/button_left.png")
|
||||
private val RIGHT_BUTTON = cobblemonResource("textures/gui/bag/button_right.png")
|
||||
}
|
||||
|
||||
var enabled = true
|
||||
|
||||
override fun renderWidget(context: GuiGraphics, mouseX: Int, mouseY: Int, partialTick: Float) {
|
||||
blitk(
|
||||
matrixStack = context.pose(),
|
||||
texture = if (leftButton) LEFT_BUTTON else RIGHT_BUTTON,
|
||||
x = x / 0.5F, y = y / 0.5F,
|
||||
width = WIDTH * 2, height = HEIGHT * 2,
|
||||
textureHeight = 40,
|
||||
vOffset = if (enabled) 20 else 0,
|
||||
scale = 0.5f
|
||||
)
|
||||
}
|
||||
|
||||
override fun playDownSound(handler: SoundManager) {}
|
||||
}
|
||||
@@ -0,0 +1,416 @@
|
||||
/*
|
||||
* 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.bag
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonNetwork.sendToServer
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.bag.BagCategories
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
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.drawProfilePokemon
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.client.render.drawScaledTextJustifiedRight
|
||||
import com.cobblemon.mod.common.client.render.getDepletableRedGreen
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.FloatingState
|
||||
import com.cobblemon.mod.common.item.bag.CobblemonBagMenu
|
||||
import com.cobblemon.mod.common.item.battle.BagItem
|
||||
import com.cobblemon.mod.common.net.messages.client.bag.UpdateBagMenuDataPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.bag.UseItemOnPokemonFromBagPacket
|
||||
import com.cobblemon.mod.common.pokemon.Gender
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import com.cobblemon.mod.common.util.math.fromEulerXYZDegrees
|
||||
import juuxel.adorn.util.Colors
|
||||
import net.fabricmc.api.EnvType
|
||||
import net.fabricmc.api.Environment
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen
|
||||
import net.minecraft.client.resources.sounds.SimpleSoundInstance
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.sounds.SoundEvent
|
||||
import net.minecraft.world.entity.player.Inventory
|
||||
import net.minecraft.world.inventory.ClickType
|
||||
import net.minecraft.world.inventory.Slot
|
||||
import org.joml.Quaternionf
|
||||
import org.joml.Vector3f
|
||||
import kotlin.math.min
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
class CobblemonBagScreen(
|
||||
menu: CobblemonBagMenu,
|
||||
playerInventory: Inventory,
|
||||
title: Component
|
||||
): AbstractContainerScreen<CobblemonBagMenu>(
|
||||
menu,
|
||||
playerInventory,
|
||||
Component.translatable("cobblemon.container.bag")
|
||||
) {
|
||||
companion object {
|
||||
private const val BACKGROUND_HEIGHT = 197
|
||||
private const val BACKGROUND_WIDTH = 184
|
||||
|
||||
private val BACKGROUND = cobblemonResource("textures/gui/bag/bag_base.png")
|
||||
private val SCROLL_TRACK = cobblemonResource("textures/gui/bag/scrollbar_track.png")
|
||||
private val SCROLL_SLIDE = cobblemonResource("textures/gui/bag/scrollbar_slide.png")
|
||||
private val PARTY_SLOT_BASE = cobblemonResource("textures/gui/bag/party_slot_base.png")
|
||||
private val PARTY_SLOT_COLLAPSED = cobblemonResource("textures/gui/bag/party_slot_collapsed.png")
|
||||
private val PARTY_SLOT = cobblemonResource("textures/gui/bag/party_slot.png")
|
||||
private val PARTY_SLOT_FAINTED = cobblemonResource("textures/gui/bag/party_slot_fainted.png")
|
||||
private val GENDER_ICON_MALE = cobblemonResource("textures/gui/party/party_gender_male.png")
|
||||
private val GENDER_ICON_FEMALE = cobblemonResource("textures/gui/party/party_gender_female.png")
|
||||
}
|
||||
|
||||
val categoriesWidgets = mutableListOf<BagCategoryButton>()
|
||||
lateinit var allItemsCategoryWidget: BagCategoryButton
|
||||
lateinit var leftCategoryPageButton: BagCategoryPageButton
|
||||
lateinit var rightCategoryPageButton: BagCategoryPageButton
|
||||
var currentCategoryPage = 0
|
||||
var lastCategory = menu.currentlySelectedCategory
|
||||
var lastScroll = menu.scroll
|
||||
var scrolling = false
|
||||
|
||||
init {
|
||||
this.imageWidth = BACKGROUND_WIDTH + 69
|
||||
this.imageHeight = BACKGROUND_HEIGHT + 27
|
||||
}
|
||||
|
||||
override fun init() {
|
||||
super.init()
|
||||
this.leftPos -= 34
|
||||
|
||||
for (i in 0..3) {
|
||||
if (i < BagCategories.getOrderedCategoriesList().size) {
|
||||
categoriesWidgets.add(
|
||||
BagCategoryButton(leftPos + 76 + i * 33, topPos, this, i) {
|
||||
if (menu.currentlySelectedCategory != i) {
|
||||
menu.changeCategory(i)
|
||||
playSound(CobblemonSounds.ITEM_BAG_CLICK)
|
||||
}
|
||||
}.also { addRenderableWidget(it) }
|
||||
)
|
||||
} else break
|
||||
}
|
||||
|
||||
allItemsCategoryWidget = BagCategoryButton(leftPos + 214, topPos, this, -1) {
|
||||
if (menu.currentlySelectedCategory != -1) {
|
||||
menu.changeCategory(-1)
|
||||
playSound(CobblemonSounds.ITEM_BAG_CLICK)
|
||||
}
|
||||
}.also { addRenderableWidget(it) }
|
||||
|
||||
leftCategoryPageButton = BagCategoryPageButton(leftPos + 218, topPos + 32, this, true) {
|
||||
if (leftCategoryPageButton.enabled) {
|
||||
cycleCategoryPage(false)
|
||||
playSound(CobblemonSounds.ITEM_BAG_CLICK)
|
||||
}
|
||||
}.also { addRenderableWidget(it) }
|
||||
rightCategoryPageButton = BagCategoryPageButton(leftPos + 229, topPos + 32, this, false) {
|
||||
if (rightCategoryPageButton.enabled) {
|
||||
cycleCategoryPage(true)
|
||||
playSound(CobblemonSounds.ITEM_BAG_CLICK)
|
||||
}
|
||||
}.also { addRenderableWidget(it) }
|
||||
|
||||
playSound(CobblemonSounds.ITEM_BAG_OPEN)
|
||||
}
|
||||
|
||||
override fun renderBg(context: GuiGraphics, partialTick: Float, mouseX: Int, mouseY: Int) {}
|
||||
override fun renderBackground(guiGraphics: GuiGraphics, mouseX: Int, mouseY: Int, partialTick: Float) {}
|
||||
|
||||
override fun renderLabels(guiGraphics: GuiGraphics, mouseX: Int, mouseY: Int) {}
|
||||
|
||||
override fun render(context: GuiGraphics, mouseX: Int, mouseY: Int, partialTick: Float) {
|
||||
renderTransparentBackground(context)
|
||||
|
||||
val matrices = context.pose()
|
||||
|
||||
// Background
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = BACKGROUND,
|
||||
x = leftPos + 69, y = topPos + 27,
|
||||
width = BACKGROUND_WIDTH, height = BACKGROUND_HEIGHT
|
||||
)
|
||||
|
||||
//Scroll
|
||||
val scrollYOffset = if (menu.maxScroll == 0) {
|
||||
if (menu.scroll == 0) 0 else 53
|
||||
} else ((min(menu.scroll, menu.maxScroll).toFloat() / menu.maxScroll) * 53).toInt()
|
||||
val trackHeight = 71 - scrollYOffset - 13
|
||||
|
||||
if (trackHeight > 0) {
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = SCROLL_TRACK,
|
||||
x = leftPos + 230, y = topPos + 49 + (71 - trackHeight),
|
||||
width = 9, height = trackHeight,
|
||||
textureHeight = 71,
|
||||
vOffset = 71 - trackHeight
|
||||
)
|
||||
}
|
||||
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = SCROLL_SLIDE,
|
||||
x = leftPos + 230, y = topPos + 49 + scrollYOffset,
|
||||
width = 9, height = 17
|
||||
)
|
||||
|
||||
// Pokemon
|
||||
val party = CobblemonClient.storage.party
|
||||
for (i in 0..5) {
|
||||
val pokemon = party.get(i)
|
||||
val slotYPosition = topPos + i * 33 + 27
|
||||
|
||||
if (pokemon != null) {
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = PARTY_SLOT_BASE,
|
||||
x = leftPos, y = slotYPosition,
|
||||
width = 67, height = 31
|
||||
)
|
||||
|
||||
val slotWidth = 32
|
||||
val slotLeft = leftPos + 11
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = if (pokemon.isFainted()) PARTY_SLOT_FAINTED else PARTY_SLOT,
|
||||
x = slotLeft, y = slotYPosition,
|
||||
width = slotWidth, height = 26,
|
||||
textureHeight = 52,
|
||||
vOffset = if (!menu.carried.isEmpty && menu.carried.item is BagItem && partySlotHovered(i, mouseX, mouseY)) 26 else 0
|
||||
)
|
||||
|
||||
val expForThisLevel = pokemon.experience - pokemon.experienceGroup.getExperience(pokemon.level)
|
||||
val expToNextLevel = pokemon.experienceGroup.getExperience(pokemon.level + 1) - pokemon.experienceGroup.getExperience(pokemon.level)
|
||||
val expRatio = expForThisLevel.toFloat() / expToNextLevel
|
||||
|
||||
val expBarHeight = expRatio * 20
|
||||
|
||||
if (expBarHeight > 0) {
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = CobblemonResources.WHITE,
|
||||
x = leftPos + 6, y = slotYPosition + 24 - expBarHeight,
|
||||
width = 1, height = expBarHeight,
|
||||
red = 0.2, green = 0.65, blue = 0.84
|
||||
)
|
||||
}
|
||||
|
||||
val hpRatio = pokemon.currentHealth.toFloat() / pokemon.maxHealth
|
||||
val hpBarHeight = hpRatio * 20
|
||||
val (red, green) = getDepletableRedGreen(hpRatio)
|
||||
|
||||
if (hpBarHeight > 0) {
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = CobblemonResources.WHITE,
|
||||
x = leftPos + 8, y = slotYPosition + 24 - hpBarHeight,
|
||||
width = 2, height = hpBarHeight,
|
||||
red = red * 0.8F, green = green * 0.8F, blue = 0.27F
|
||||
)
|
||||
}
|
||||
|
||||
// Ball Icon
|
||||
val ballIcon = cobblemonResource("textures/gui/ball/" + pokemon.caughtBall.name.path + ".png")
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = ballIcon,
|
||||
x = (leftPos + 3.5F) / 0.5F, y = (slotYPosition + 23) / 0.5F,
|
||||
width = 18, height = 22,
|
||||
textureHeight = 44,
|
||||
scale = 0.5F
|
||||
)
|
||||
|
||||
//Gender
|
||||
if (pokemon.gender != Gender.GENDERLESS) {
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = if (pokemon.gender == Gender.MALE) GENDER_ICON_MALE else GENDER_ICON_FEMALE,
|
||||
x = (leftPos + 62) / 0.5F, y = (slotYPosition + 26) / 0.5F,
|
||||
width = 5, height = 7,
|
||||
scale = 0.5F
|
||||
)
|
||||
}
|
||||
|
||||
//Status
|
||||
val status = pokemon.status?.status
|
||||
if (!pokemon.isFainted() && status != null) {
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = cobblemonResource("textures/gui/bag/status_${status.showdownName}.png"),
|
||||
x = leftPos + 1, y = slotYPosition + 9,
|
||||
width = 4, height = 14
|
||||
)
|
||||
}
|
||||
|
||||
matrices.pushPose()
|
||||
matrices.translate(slotLeft + ((slotWidth - 8) / 2.0), slotYPosition.toDouble() - 6, 0.0)
|
||||
matrices.scale(3.5F, 3.5F, 1F)
|
||||
|
||||
val state = FloatingState()
|
||||
state.currentAspects = pokemon.aspects
|
||||
drawProfilePokemon(
|
||||
species = pokemon.species.resourceIdentifier,
|
||||
matrixStack = matrices,
|
||||
rotation = Quaternionf().fromEulerXYZDegrees(Vector3f(13F, 35F, 0F)),
|
||||
state = state,
|
||||
scale = 4.5F,
|
||||
partialTicks = 0F
|
||||
)
|
||||
matrices.popPose()
|
||||
|
||||
matrices.pushPose()
|
||||
matrices.translate(0.0, 0.0, 100.0)
|
||||
// Level and Name and Gender
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = pokemon.getDisplayName(),
|
||||
x = leftPos + 14, y = slotYPosition + 26,
|
||||
scale = 0.5F
|
||||
)
|
||||
|
||||
drawScaledTextJustifiedRight(
|
||||
context = context,
|
||||
text = lang("ui.lv"),
|
||||
x = leftPos + 40, y = slotYPosition + 14,
|
||||
shadow = true,
|
||||
scale = 0.5F
|
||||
)
|
||||
|
||||
drawScaledTextJustifiedRight(
|
||||
context = context,
|
||||
text = pokemon.level.toString().text(),
|
||||
x = leftPos + 40, y = slotYPosition + 19,
|
||||
shadow = true,
|
||||
scale = 0.5F
|
||||
)
|
||||
matrices.popPose()
|
||||
} else {
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = PARTY_SLOT_COLLAPSED,
|
||||
x = leftPos + 64, y = slotYPosition,
|
||||
width = 5, height = 31
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
//Titles
|
||||
context.drawString(font, title, leftPos + 80, topPos + 33, Colors.WHITE, false)
|
||||
context.drawString(font, playerInventoryTitle, leftPos + 80, topPos + 129, 4210752, false)
|
||||
|
||||
super.render(context, mouseX, mouseY, partialTick)
|
||||
renderTooltip(context, mouseX, mouseY)
|
||||
}
|
||||
|
||||
fun partySlotHovered(index: Int, mouseX: Int, mouseY: Int): Boolean {
|
||||
val left = leftPos + 11
|
||||
val top = topPos + index * 33 + 27
|
||||
return mouseX in left..(left + 32) && mouseY in top..(top + 26)
|
||||
}
|
||||
|
||||
fun cycleCategoryPage(next: Boolean) {
|
||||
val orderedCategories = BagCategories.getOrderedCategoriesList()
|
||||
currentCategoryPage = (currentCategoryPage + if (next) 1 else -1).coerceIn(0, (orderedCategories.size - 1) / 4)
|
||||
categoriesWidgets.forEach {
|
||||
removeWidget(it)
|
||||
}
|
||||
categoriesWidgets.clear()
|
||||
for (i in 0..3) {
|
||||
val adjustedIndex = i + 4 * currentCategoryPage
|
||||
if (adjustedIndex < orderedCategories.size) {
|
||||
categoriesWidgets.add(
|
||||
BagCategoryButton(leftPos + 76 + i * 33, topPos, this, adjustedIndex) {
|
||||
playSound(CobblemonSounds.ITEM_BAG_CLICK)
|
||||
menu.changeCategory(adjustedIndex)
|
||||
}.also { addRenderableWidget(it) }
|
||||
)
|
||||
} else break
|
||||
}
|
||||
leftCategoryPageButton.enabled = currentCategoryPage > 0
|
||||
rightCategoryPageButton.enabled = currentCategoryPage < (orderedCategories.size - 1) / 4
|
||||
}
|
||||
|
||||
fun updateScrollValue(mouseY: Double) {
|
||||
val adjustedMouseY = mouseY - topPos - 49.0
|
||||
if (adjustedMouseY < 0) {
|
||||
menu.scroll = 0
|
||||
} else if (adjustedMouseY > 71) {
|
||||
menu.scroll = menu.maxScroll
|
||||
} else {
|
||||
menu.scroll = ((adjustedMouseY / 71.0) * (menu.maxScroll)).roundToInt()
|
||||
}
|
||||
menu.setupSlotsBasedOnContent()
|
||||
}
|
||||
|
||||
override fun slotClicked(slot: Slot?, slotId: Int, mouseButton: Int, type: ClickType) {
|
||||
if (slotId in CobblemonBagMenu.BAG_SLOTS && (lastCategory != menu.currentlySelectedCategory || lastScroll != menu.scroll)) {
|
||||
lastCategory = menu.currentlySelectedCategory
|
||||
lastScroll = menu.scroll
|
||||
sendToServer(UpdateBagMenuDataPacket(menu.currentlySelectedCategory, menu.scroll)) // Synchronize this data
|
||||
}
|
||||
super.slotClicked(slot, slotId, mouseButton, type)
|
||||
}
|
||||
|
||||
override fun mouseScrolled(mouseX: Double, mouseY: Double, scrollX: Double, scrollY: Double): Boolean {
|
||||
if (scrollY < 0 && menu.scroll < menu.maxScroll) {
|
||||
menu.scroll += 1
|
||||
} else if (scrollY > 0 && menu.scroll > 0) {
|
||||
menu.scroll -= 1
|
||||
}
|
||||
menu.setupSlotsBasedOnContent()
|
||||
return true
|
||||
}
|
||||
|
||||
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
||||
if (mouseX in (leftPos + 229.0)..(leftPos + 240.0) && mouseY in (topPos + 49.0)..(topPos + 120.0)) {
|
||||
scrolling = true
|
||||
updateScrollValue(mouseY)
|
||||
return true
|
||||
}
|
||||
val party = CobblemonClient.storage.party
|
||||
if (!menu.carried.isEmpty && menu.carried.item is BagItem) {
|
||||
for (i in 0..5) {
|
||||
if (party.get(i) != null && partySlotHovered(i, mouseX.toInt(), mouseY.toInt())) {
|
||||
playSound(CobblemonSounds.GUI_CLICK)
|
||||
sendToServer(UseItemOnPokemonFromBagPacket(i))
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.mouseClicked(mouseX, mouseY, button)
|
||||
}
|
||||
|
||||
override fun mouseReleased(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
||||
scrolling = false
|
||||
return super.mouseReleased(mouseX, mouseY, button)
|
||||
}
|
||||
|
||||
override fun mouseDragged(mouseX: Double, mouseY: Double, button: Int, dragX: Double, dragY: Double): Boolean {
|
||||
if (scrolling) {
|
||||
updateScrollValue(mouseY)
|
||||
return true
|
||||
}
|
||||
return super.mouseDragged(mouseX, mouseY, button, dragX, dragY)
|
||||
}
|
||||
|
||||
fun playSound(soundEvent: SoundEvent) {
|
||||
Minecraft.getInstance().soundManager.play(SimpleSoundInstance.forUI(soundEvent, 1.0F))
|
||||
}
|
||||
|
||||
override fun onClose() {
|
||||
Minecraft.getInstance().soundManager.play(SimpleSoundInstance.forUI(CobblemonSounds.ITEM_BAG_CLOSE, 1.0F))
|
||||
super.onClose()
|
||||
}
|
||||
}
|
||||
@@ -28,9 +28,9 @@ import org.joml.Vector3f
|
||||
|
||||
open class PartySlot(
|
||||
x: Int, y: Int,
|
||||
private val pokemon: TradeStartedPacket.TradeablePokemon?,
|
||||
val pokemon: TradeStartedPacket.TradeablePokemon?,
|
||||
private val parent: TradeGUI,
|
||||
private val isOpposing: Boolean = false,
|
||||
val isOpposing: Boolean = false,
|
||||
onPress: OnPress
|
||||
) : Button(x, y, SIZE, SIZE, Component.literal("PartySlot"), onPress, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
val state = FloatingState()
|
||||
@@ -42,6 +42,8 @@ open class PartySlot(
|
||||
private val genderIconFemale = cobblemonResource("textures/gui/pc/gender_icon_female.png")
|
||||
private val selectPointerResource = cobblemonResource("textures/gui/pc/pc_pointer.png")
|
||||
private val untradeableResource = cobblemonResource("textures/gui/trade/trade_slot_icon_locked.png")
|
||||
private val tradePartySlotSelectedResource = cobblemonResource("textures/gui/trade/trade_party_slot_selected.png")
|
||||
private val tradePartySlotSelectedOpposingResource = cobblemonResource("textures/gui/trade/trade_party_slot_selected_opposing.png")
|
||||
}
|
||||
|
||||
override fun playDownSound(soundManager: SoundManager) {
|
||||
@@ -60,6 +62,17 @@ open class PartySlot(
|
||||
)
|
||||
}
|
||||
|
||||
if (hasSelected()) {
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = if (isOpposing) tradePartySlotSelectedOpposingResource else tradePartySlotSelectedResource,
|
||||
x = x - 2,
|
||||
y = y - 2,
|
||||
width = 29,
|
||||
height = 29
|
||||
)
|
||||
}
|
||||
|
||||
if (pokemon != null) {
|
||||
// context.enableScissor(x - 2, y + 2, x + SIZE + 4, y + SIZE + 4)
|
||||
// Render Pokémon
|
||||
@@ -118,7 +131,16 @@ open class PartySlot(
|
||||
}
|
||||
|
||||
matrices.popPose()
|
||||
if (hasSelected()) {
|
||||
|
||||
val isViewed = if (isOpposing) {
|
||||
parent.opposingOfferedPokemon?.uuid == pokemon.pokemonId
|
||||
} else {
|
||||
parent.offeredPokemon?.uuid == pokemon.pokemonId
|
||||
}
|
||||
|
||||
if (isViewed && pokemon.tradeable) {
|
||||
matrices.pushPose()
|
||||
matrices.translate(0.0, 0.0, 200.0)
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = selectPointerResource,
|
||||
@@ -128,6 +150,7 @@ open class PartySlot(
|
||||
height = 8,
|
||||
scale = TradeGUI.SCALE
|
||||
)
|
||||
matrices.popPose()
|
||||
}
|
||||
|
||||
// Held Item
|
||||
@@ -145,8 +168,9 @@ open class PartySlot(
|
||||
}
|
||||
|
||||
open fun hasSelected(): Boolean {
|
||||
val offeredPokemon = if (isOpposing) parent.trade.oppositeOffer.get() else parent.trade.myOffer.get()
|
||||
return pokemon?.pokemonId == offeredPokemon?.uuid && pokemon != null
|
||||
if (pokemon == null) return false
|
||||
val offeredPokemons = if (isOpposing) parent.trade.oppositeOffer.get() else parent.trade.myOffer.get()
|
||||
return offeredPokemons.any { it.uuid == pokemon.pokemonId }
|
||||
}
|
||||
|
||||
fun isHovered(mouseX: Int, mouseY: Int) = pokemon?.tradeable != false && mouseX.toFloat() in (x.toFloat()..(x.toFloat() + SIZE)) && mouseY.toFloat() in (y.toFloat()..(y.toFloat() + SIZE))
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.cobblemon.mod.common.client.gui.summary.widgets.common.reformatNature
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.client.render.drawScaledTextJustifiedRight
|
||||
import com.cobblemon.mod.common.client.trade.ClientTrade
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeStartedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeStartedPacket.TradeablePokemon
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.*
|
||||
import com.cobblemon.mod.common.pokemon.Gender
|
||||
@@ -98,15 +99,23 @@ class TradeGUI(
|
||||
private val tradeAnimationArrowsResource = cobblemonResource("textures/gui/trade/trade_animation_arrows.png")
|
||||
}
|
||||
|
||||
private var offeredPokemonModel: ModelWidget? = null
|
||||
private var opposingOfferedPokemonModel: ModelWidget? = null
|
||||
private var offeredPokemonModels: MutableList<ModelWidget> = mutableListOf()
|
||||
private var opposingOfferedPokemonModels: MutableList<ModelWidget> = mutableListOf()
|
||||
|
||||
private lateinit var offeredPokemonMarkings: MarkingsWidget
|
||||
private lateinit var opposingOfferedPokemonMarkings: MarkingsWidget
|
||||
|
||||
var selectedPartyIndices = mutableListOf<Int>()
|
||||
var offeredPokemons: MutableList<Pokemon> = mutableListOf()
|
||||
var opposingPokemons: MutableList<Pokemon> = mutableListOf()
|
||||
|
||||
// For backwards compatibility where single is referenced in rendering text info
|
||||
var offeredPokemon: Pokemon? = null
|
||||
var opposingOfferedPokemon: Pokemon? = null
|
||||
|
||||
var myGridMode = true
|
||||
var opposingGridMode = true
|
||||
|
||||
var ticksElapsed = 0
|
||||
var protectiveTicks = 0
|
||||
var selectPointerOffsetY = 0
|
||||
@@ -125,30 +134,67 @@ class TradeGUI(
|
||||
}
|
||||
|
||||
trade.completedEmitter.subscribe {
|
||||
val (pokemonId1, pokemonId2) = it
|
||||
val myTradedPokemon = party.find { it?.pokemonId == pokemonId1 }
|
||||
val theirTradedPokemon = traderParty.find { it?.pokemonId == pokemonId2 }
|
||||
if (myTradedPokemon == null || theirTradedPokemon == null) {
|
||||
val (pokemonIds1, pokemonIds2) = it
|
||||
val myTradedPokemons = pokemonIds1.mapNotNull { id -> party.find { it?.pokemonId == id } }
|
||||
val theirTradedPokemons = pokemonIds2.mapNotNull { id -> traderParty.find { it?.pokemonId == id } }
|
||||
if (myTradedPokemons.isEmpty() || theirTradedPokemons.isEmpty()) {
|
||||
CobblemonNetwork.sendToServer(CancelTradePacket())
|
||||
return@subscribe onClose()
|
||||
}
|
||||
val tradedSlot = party.indexOf(myTradedPokemon)
|
||||
val opposingTradedSlot = traderParty.indexOf(theirTradedPokemon)
|
||||
party[tradedSlot] = theirTradedPokemon
|
||||
traderParty[opposingTradedSlot] = myTradedPokemon
|
||||
|
||||
myTradedPokemons.forEach { pk ->
|
||||
val idx = party.indexOf(pk)
|
||||
if (idx != -1) party[idx] = null
|
||||
}
|
||||
theirTradedPokemons.forEach { pk ->
|
||||
val idx = traderParty.indexOf(pk)
|
||||
if (idx != -1) traderParty[idx] = null
|
||||
}
|
||||
|
||||
val newSelectedIndices = mutableListOf<Int>()
|
||||
theirTradedPokemons.forEach { pk ->
|
||||
val emptyIdx = party.indexOf(null)
|
||||
if (emptyIdx != -1) {
|
||||
party[emptyIdx] = pk
|
||||
}
|
||||
}
|
||||
myTradedPokemons.forEach { pk ->
|
||||
val emptyIdx = traderParty.indexOf(null)
|
||||
if (emptyIdx != -1) traderParty[emptyIdx] = pk
|
||||
}
|
||||
|
||||
val compactUI = { list: MutableList<TradeStartedPacket.TradeablePokemon?> ->
|
||||
val nonNulls = list.filterNotNull()
|
||||
list.clear()
|
||||
list.addAll(nonNulls)
|
||||
while (list.size < 6) list.add(null)
|
||||
}
|
||||
compactUI(party)
|
||||
compactUI(traderParty)
|
||||
|
||||
theirTradedPokemons.forEach { pk ->
|
||||
val idx = party.indexOf(pk)
|
||||
if (idx != -1) newSelectedIndices.add(idx)
|
||||
}
|
||||
|
||||
trade.oppositeAcceptedMyOffer.set(false)
|
||||
CobblemonNetwork.sendToServer(UpdateTradeOfferPacket(Pair(theirTradedPokemon.pokemonId, PartyPosition(tradedSlot))))
|
||||
selectedPartyIndices.clear()
|
||||
selectedPartyIndices.addAll(newSelectedIndices)
|
||||
|
||||
val newOffers = selectedPartyIndices.mapNotNull { idx ->
|
||||
party[idx]?.let { it.pokemonId to PartyPosition(idx) }
|
||||
}
|
||||
CobblemonNetwork.sendToServer(UpdateTradeOfferPacket(newOffers))
|
||||
|
||||
rebuildWidgets()
|
||||
}
|
||||
|
||||
trade.oppositeOffer.subscribe { newOffer: Pokemon? ->
|
||||
setOfferedPokemon(pokemon = newOffer, isOpposing = true)
|
||||
trade.oppositeOffer.subscribe { newOffer: List<Pokemon> ->
|
||||
setOfferedPokemon(pokemonList = newOffer, isOpposing = true)
|
||||
}
|
||||
|
||||
trade.myOffer.subscribe { myOffer: Pokemon? ->
|
||||
setOfferedPokemon(pokemon = myOffer)
|
||||
trade.myOffer.subscribe { myOffer: List<Pokemon> ->
|
||||
setOfferedPokemon(pokemonList = myOffer)
|
||||
}
|
||||
|
||||
trade.oppositeAcceptedMyOffer.subscribe {
|
||||
@@ -216,9 +262,16 @@ class TradeGUI(
|
||||
pokemon = pokemon,
|
||||
parent = this,
|
||||
onPress = {
|
||||
if (!trade.acceptedOppositeOffer && !tradeProcessing) {
|
||||
val pk = if (offeredPokemon?.uuid == pokemon?.pokemonId) null else pokemon
|
||||
CobblemonNetwork.sendToServer(UpdateTradeOfferPacket(pk?.let { it.pokemonId to PartyPosition(partyIndex) }))
|
||||
if (!trade.acceptedOppositeOffer && !tradeProcessing && pokemon != null) {
|
||||
if (selectedPartyIndices.contains(partyIndex)) {
|
||||
selectedPartyIndices.remove(partyIndex)
|
||||
} else if (selectedPartyIndices.size < 6) {
|
||||
selectedPartyIndices.add(partyIndex)
|
||||
}
|
||||
val newOffers = selectedPartyIndices.mapNotNull { idx ->
|
||||
party[idx]?.let { it.pokemonId to PartyPosition(idx) }
|
||||
}
|
||||
CobblemonNetwork.sendToServer(UpdateTradeOfferPacket(newOffers))
|
||||
playSound(CobblemonSounds.GUI_CLICK)
|
||||
}
|
||||
}
|
||||
@@ -250,8 +303,8 @@ class TradeGUI(
|
||||
).also { widget -> addRenderableWidget(widget) }
|
||||
}
|
||||
|
||||
setOfferedPokemon(pokemon = offeredPokemon, isOpposing = false)
|
||||
setOfferedPokemon(pokemon = opposingOfferedPokemon, isOpposing = true)
|
||||
setOfferedPokemon(pokemonList = offeredPokemons.toList(), isOpposing = false)
|
||||
setOfferedPokemon(pokemonList = opposingPokemons.toList(), isOpposing = true)
|
||||
|
||||
offeredPokemonMarkings = MarkingsWidget(x + 74.5, y + 21, offeredPokemon, false)
|
||||
opposingOfferedPokemonMarkings = MarkingsWidget(x + 177.5, y + 21, opposingOfferedPokemon, false)
|
||||
@@ -284,7 +337,7 @@ class TradeGUI(
|
||||
if (tradeAnimationProgress > REVERSE_ANIMATION_TICK)
|
||||
(REVERSE_ANIMATION_TICK + TRADE_ANIMATION_FRAMES - tradeAnimationProgress)
|
||||
else (tradeAnimationProgress - MODEL_SCALE_BUFFER_FRAMES)
|
||||
) * TRADE_ANIMATION_HEIGHT
|
||||
) * TRADE_ANIMATION_HEIGHT
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = tradeAnimationResource,
|
||||
@@ -313,20 +366,56 @@ class TradeGUI(
|
||||
// Render Model Portraits
|
||||
var scale = PORTRAIT_SCALE
|
||||
var scaleOffsetY = PORTRAIT_MODEL_OFFSET_Y
|
||||
var isShrinking = false
|
||||
if (tradeProcessing) {
|
||||
val scaleInterval = if (tradeAnimationProgress > REVERSE_ANIMATION_TICK) (MAX_TRADE_PROGRESS - tradeAnimationProgress) else tradeAnimationProgress
|
||||
scale = (PORTRAIT_SCALE - (scaleInterval * PORTRAIT_SCALE_MULTIPLIER)).coerceIn(0F, PORTRAIT_SCALE)
|
||||
scaleOffsetY = (45.0 - (45.0 / PORTRAIT_SCALE) * scale) + PORTRAIT_MODEL_OFFSET_Y
|
||||
isShrinking = true
|
||||
}
|
||||
val shrinkPercentage = if (isShrinking) 1.0F - (scale / PORTRAIT_SCALE) else 0.0F
|
||||
val myCenterXDest = x + 70 + (PORTRAIT_SIZE / 2.0)
|
||||
val myCenterYDest = y + 30 + (PORTRAIT_SIZE / 2.0)
|
||||
val opCenterXDest = x + 145 + (PORTRAIT_SIZE / 2.0)
|
||||
val opCenterYDest = y + 30 + (PORTRAIT_SIZE / 2.0)
|
||||
|
||||
if (scale > 0F) {
|
||||
context.enableScissor(backgroundX, backgroundY, backgroundX + BASE_BACKGROUND_WIDTH, backgroundY + BASE_BACKGROUND_HEIGHT)
|
||||
offeredPokemonModel?.baseScale = scale
|
||||
offeredPokemonModel?.offsetY = scaleOffsetY
|
||||
offeredPokemonModel?.render(context, mouseX, mouseY, delta)
|
||||
|
||||
opposingOfferedPokemonModel?.baseScale = scale
|
||||
opposingOfferedPokemonModel?.offsetY = scaleOffsetY
|
||||
opposingOfferedPokemonModel?.render(context, mouseX, mouseY, delta)
|
||||
offeredPokemonModels.forEachIndexed { i, model ->
|
||||
val posAndScale = getModelPositionAndScale(i, offeredPokemons.size, x + 70, y + 30)
|
||||
val originalScale = posAndScale.second
|
||||
model.baseScale = if (isShrinking) (originalScale / PORTRAIT_SCALE) * scale else originalScale
|
||||
model.offsetY = if (isShrinking) scaleOffsetY else PORTRAIT_MODEL_OFFSET_Y
|
||||
|
||||
val startCenterX = posAndScale.first.first + (PORTRAIT_SIZE / 2.0)
|
||||
val startCenterY = posAndScale.first.second + (PORTRAIT_SIZE / 2.0)
|
||||
|
||||
context.pose().pushPose()
|
||||
context.pose().translate((myCenterXDest - startCenterX) * shrinkPercentage, (myCenterYDest - startCenterY) * shrinkPercentage, 0.0)
|
||||
|
||||
model.render(context, mouseX, mouseY, delta)
|
||||
|
||||
context.pose().popPose()
|
||||
}
|
||||
|
||||
opposingOfferedPokemonModels.forEachIndexed { i, model ->
|
||||
val posAndScale = getModelPositionAndScale(i, opposingPokemons.size, x + 145, y + 30)
|
||||
val originalScale = posAndScale.second
|
||||
model.baseScale = if (isShrinking) (originalScale / PORTRAIT_SCALE) * scale else originalScale
|
||||
model.offsetY = if (isShrinking) scaleOffsetY else PORTRAIT_MODEL_OFFSET_Y
|
||||
|
||||
val startCenterX = posAndScale.first.first + (PORTRAIT_SIZE / 2.0)
|
||||
val startCenterY = posAndScale.first.second + (PORTRAIT_SIZE / 2.0)
|
||||
|
||||
context.pose().pushPose()
|
||||
context.pose().translate((opCenterXDest - startCenterX) * shrinkPercentage, (opCenterYDest - startCenterY) * shrinkPercentage, 0.0)
|
||||
|
||||
model.render(context, mouseX, mouseY, delta)
|
||||
|
||||
context.pose().popPose()
|
||||
}
|
||||
|
||||
context.disableScissor()
|
||||
}
|
||||
|
||||
@@ -341,8 +430,46 @@ class TradeGUI(
|
||||
|
||||
renderInfoLabels(context, x, y)
|
||||
|
||||
renderPokemonInfo(offeredPokemon, false, context, x, y, mouseX, mouseY)
|
||||
renderPokemonInfo(opposingOfferedPokemon, true, context, x, y, mouseX, mouseY)
|
||||
children().filterIsInstance<PartySlot>().forEach { slot ->
|
||||
if (slot.isHovered(mouseX, mouseY)) {
|
||||
val hoveredId = slot.pokemon?.pokemonId
|
||||
if (slot.isOpposing && slot.hasSelected()) {
|
||||
opposingPokemons.find { it.uuid == hoveredId }?.let { opposingOfferedPokemon = it }
|
||||
} else if (!slot.isOpposing) {
|
||||
val matchingModel = offeredPokemons.find { it.uuid == hoveredId }
|
||||
if (matchingModel != null) {
|
||||
offeredPokemon = matchingModel
|
||||
} else {
|
||||
val realPokemon = com.cobblemon.mod.common.client.CobblemonClient.storage.party.find { it?.uuid == hoveredId }
|
||||
if (realPokemon != null) {
|
||||
offeredPokemon = realPokemon
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val currentOffered = offeredPokemon
|
||||
if (currentOffered != null) {
|
||||
renderPokemonInfo(currentOffered, false, context, x, y, mouseX, mouseY)
|
||||
if (::offeredPokemonMarkings.isInitialized) {
|
||||
offeredPokemonMarkings.visible = true
|
||||
if (offeredPokemonMarkings.pokemon != currentOffered) offeredPokemonMarkings.setActivePokemon(currentOffered)
|
||||
}
|
||||
} else {
|
||||
if (::offeredPokemonMarkings.isInitialized) offeredPokemonMarkings.visible = false
|
||||
}
|
||||
|
||||
val currentOpposing = opposingOfferedPokemon
|
||||
if (currentOpposing != null) {
|
||||
renderPokemonInfo(currentOpposing, true, context, x, y, mouseX, mouseY)
|
||||
if (::opposingOfferedPokemonMarkings.isInitialized) {
|
||||
opposingOfferedPokemonMarkings.visible = true
|
||||
if (opposingOfferedPokemonMarkings.pokemon != currentOpposing) opposingOfferedPokemonMarkings.setActivePokemon(currentOpposing)
|
||||
}
|
||||
} else {
|
||||
if (::opposingOfferedPokemonMarkings.isInitialized) opposingOfferedPokemonMarkings.visible = false
|
||||
}
|
||||
|
||||
if (trade.acceptedOppositeOffer) {
|
||||
blitk(
|
||||
@@ -431,19 +558,25 @@ class TradeGUI(
|
||||
|
||||
super.render(context, mouseX, mouseY, delta)
|
||||
|
||||
// Item Tooltip
|
||||
if (offeredPokemon != null && !offeredPokemon!!.heldItemNoCopy().isEmpty) {
|
||||
val itemX = x + 50
|
||||
val itemY = y + 125
|
||||
val itemHovered = mouseX.toFloat() in (itemX.toFloat()..(itemX.toFloat() + 16)) && mouseY.toFloat() in (itemY.toFloat()..(itemY.toFloat() + 16))
|
||||
if (itemHovered) context.renderTooltip(Minecraft.getInstance().font, offeredPokemon!!.heldItemNoCopy(), mouseX, mouseY)
|
||||
val ttOffered = offeredPokemon
|
||||
if (ttOffered != null) {
|
||||
// Item Tooltip
|
||||
if (!ttOffered.heldItemNoCopy().isEmpty) {
|
||||
val itemX = x + 50
|
||||
val itemY = y + 125
|
||||
val itemHovered = mouseX.toFloat() in (itemX.toFloat()..(itemX.toFloat() + 16)) && mouseY.toFloat() in (itemY.toFloat()..(itemY.toFloat() + 16))
|
||||
if (itemHovered) context.renderTooltip(Minecraft.getInstance().font, ttOffered.heldItemNoCopy(), mouseX, mouseY)
|
||||
}
|
||||
}
|
||||
|
||||
if (opposingOfferedPokemon != null && !opposingOfferedPokemon!!.heldItemNoCopy().isEmpty) {
|
||||
val itemX = x + 227
|
||||
val itemY = y + 125
|
||||
val itemHovered = mouseX.toFloat() in (itemX.toFloat()..(itemX.toFloat() + 16)) && mouseY.toFloat() in (itemY.toFloat()..(itemY.toFloat() + 16))
|
||||
if (itemHovered) context.renderTooltip(Minecraft.getInstance().font, opposingOfferedPokemon!!.heldItemNoCopy(), mouseX, mouseY)
|
||||
val ttOpposing = opposingOfferedPokemon
|
||||
if (ttOpposing != null) {
|
||||
if (!ttOpposing.heldItemNoCopy().isEmpty) {
|
||||
val itemX = x + 227
|
||||
val itemY = y + 125
|
||||
val itemHovered = mouseX.toFloat() in (itemX.toFloat()..(itemX.toFloat() + 16)) && mouseY.toFloat() in (itemY.toFloat()..(itemY.toFloat() + 16))
|
||||
if (itemHovered) context.renderTooltip(Minecraft.getInstance().font, ttOpposing.heldItemNoCopy(), mouseX, mouseY)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -480,11 +613,13 @@ class TradeGUI(
|
||||
}
|
||||
|
||||
if (tradeAnimationProgress == (MAX_TRADE_PROGRESS + CRY_BUFFER)) {
|
||||
if (offeredPokemonModel !== null && opposingOfferedPokemonModel !== null) {
|
||||
offeredPokemonModel!!.state.activeAnimations.clear()
|
||||
offeredPokemonModel!!.state.addFirstAnimation(setOf("cry"))
|
||||
opposingOfferedPokemonModel!!.state.activeAnimations.clear()
|
||||
opposingOfferedPokemonModel!!.state.addFirstAnimation(setOf("cry"))
|
||||
offeredPokemonModels.forEach {
|
||||
it.state.activeAnimations.clear()
|
||||
it.state.addFirstAnimation(setOf("cry"))
|
||||
}
|
||||
opposingOfferedPokemonModels.forEach {
|
||||
it.state.activeAnimations.clear()
|
||||
it.state.addFirstAnimation(setOf("cry"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -515,41 +650,140 @@ class TradeGUI(
|
||||
|
||||
override fun renderMenuBackground(context: GuiGraphics) {}
|
||||
|
||||
private fun setOfferedPokemon(pokemon: Pokemon?, isOpposing: Boolean = false) {
|
||||
private fun setOfferedPokemon(pokemonList: List<Pokemon>, isOpposing: Boolean = false) {
|
||||
protectiveTicks = 20
|
||||
if (isOpposing) {
|
||||
val wasEmpty = opposingPokemons.isEmpty()
|
||||
val currentViewedUuid = if (opposingGridMode) null else opposingOfferedPokemon?.uuid
|
||||
opposingPokemons.clear()
|
||||
opposingPokemons.addAll(pokemonList)
|
||||
|
||||
val matchingPokemon = opposingPokemons.find { it.uuid == currentViewedUuid }
|
||||
|
||||
if (matchingPokemon != null) {
|
||||
opposingOfferedPokemon = matchingPokemon
|
||||
if (::opposingOfferedPokemonMarkings.isInitialized) opposingOfferedPokemonMarkings.setActivePokemon(opposingOfferedPokemon)
|
||||
} else {
|
||||
opposingOfferedPokemon = opposingPokemons.lastOrNull()
|
||||
if (::opposingOfferedPokemonMarkings.isInitialized) opposingOfferedPokemonMarkings.setActivePokemon(opposingOfferedPokemon)
|
||||
if (wasEmpty && opposingOfferedPokemon != null) {
|
||||
opposingGridMode = false
|
||||
} else if (!opposingGridMode) {
|
||||
opposingGridMode = true
|
||||
}
|
||||
}
|
||||
trade.acceptedOppositeOffer = false
|
||||
} else {
|
||||
val wasEmpty = offeredPokemons.isEmpty()
|
||||
val currentViewedUuid = if (myGridMode) null else offeredPokemon?.uuid
|
||||
offeredPokemons.clear()
|
||||
offeredPokemons.addAll(pokemonList)
|
||||
|
||||
val matchingPokemon = offeredPokemons.find { it.uuid == currentViewedUuid }
|
||||
|
||||
if (matchingPokemon != null) {
|
||||
offeredPokemon = matchingPokemon
|
||||
if (::offeredPokemonMarkings.isInitialized) offeredPokemonMarkings.setActivePokemon(offeredPokemon)
|
||||
} else {
|
||||
offeredPokemon = offeredPokemons.lastOrNull()
|
||||
if (::offeredPokemonMarkings.isInitialized) offeredPokemonMarkings.setActivePokemon(offeredPokemon)
|
||||
if (wasEmpty && offeredPokemon != null) {
|
||||
myGridMode = false
|
||||
} else if (!myGridMode) {
|
||||
myGridMode = true
|
||||
}
|
||||
}
|
||||
}
|
||||
rebuildSelectedModels(isOpposing)
|
||||
}
|
||||
|
||||
private fun rebuildSelectedModels(isOpposing: Boolean) {
|
||||
val x = (width - BASE_WIDTH) / 2
|
||||
val y = (height - BASE_HEIGHT) / 2
|
||||
|
||||
if (isOpposing) {
|
||||
opposingOfferedPokemon = pokemon
|
||||
opposingOfferedPokemonModel = if (pokemon != null) ModelWidget(
|
||||
pX = x + 145,
|
||||
pY = y + 30,
|
||||
pWidth = PORTRAIT_SIZE,
|
||||
pHeight = PORTRAIT_SIZE,
|
||||
pokemon = pokemon.asRenderablePokemon(),
|
||||
baseScale = PORTRAIT_SCALE,
|
||||
rotationY = 35F,
|
||||
offsetY = PORTRAIT_MODEL_OFFSET_Y
|
||||
) else null
|
||||
if (::opposingOfferedPokemonMarkings.isInitialized) opposingOfferedPokemonMarkings.setActivePokemon(opposingOfferedPokemon)
|
||||
trade.acceptedOppositeOffer = false
|
||||
opposingOfferedPokemonModels.clear()
|
||||
val total = opposingPokemons.size
|
||||
opposingPokemons.forEachIndexed { i, pk ->
|
||||
val (pos, currentScale) = getModelPositionAndScale(i, total, x + 145, y + 30)
|
||||
opposingOfferedPokemonModels.add(ModelWidget(
|
||||
pX = pos.first, pY = pos.second,
|
||||
pWidth = PORTRAIT_SIZE, pHeight = PORTRAIT_SIZE,
|
||||
pokemon = pk.asRenderablePokemon(),
|
||||
baseScale = currentScale,
|
||||
rotationY = 35F,
|
||||
offsetY = PORTRAIT_MODEL_OFFSET_Y
|
||||
))
|
||||
}
|
||||
} else {
|
||||
offeredPokemon = pokemon
|
||||
offeredPokemonModel = if (pokemon != null) ModelWidget(
|
||||
pX = x + 70,
|
||||
pY = y + 30,
|
||||
pWidth = PORTRAIT_SIZE,
|
||||
pHeight = PORTRAIT_SIZE,
|
||||
pokemon = pokemon.asRenderablePokemon(),
|
||||
baseScale = PORTRAIT_SCALE,
|
||||
rotationY = 325F,
|
||||
offsetY = PORTRAIT_MODEL_OFFSET_Y
|
||||
) else null
|
||||
if (::offeredPokemonMarkings.isInitialized) offeredPokemonMarkings.setActivePokemon(offeredPokemon)
|
||||
offeredPokemonModels.clear()
|
||||
val total = offeredPokemons.size
|
||||
offeredPokemons.forEachIndexed { i, pk ->
|
||||
val (pos, currentScale) = getModelPositionAndScale(i, total, x + 70, y + 30)
|
||||
offeredPokemonModels.add(ModelWidget(
|
||||
pX = pos.first, pY = pos.second,
|
||||
pWidth = PORTRAIT_SIZE, pHeight = PORTRAIT_SIZE,
|
||||
pokemon = pk.asRenderablePokemon(),
|
||||
baseScale = currentScale,
|
||||
rotationY = 325F,
|
||||
offsetY = PORTRAIT_MODEL_OFFSET_Y
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getModelPositionAndScale(index: Int, total: Int, baseX: Int, baseY: Int): Pair<Pair<Int, Int>, Float> {
|
||||
val scale = when (total) {
|
||||
1 -> PORTRAIT_SCALE
|
||||
2 -> PORTRAIT_SCALE * 0.75f
|
||||
3 -> PORTRAIT_SCALE * 0.65f
|
||||
4 -> PORTRAIT_SCALE * 0.55f
|
||||
else -> PORTRAIT_SCALE * 0.5f
|
||||
}
|
||||
|
||||
if (total <= 1) {
|
||||
return Pair(Pair(baseX, baseY), scale)
|
||||
}
|
||||
|
||||
val rowLength1 = when (total) {
|
||||
2, 3, 4 -> 2
|
||||
else -> 3
|
||||
}
|
||||
val rowLength2 = total - rowLength1
|
||||
|
||||
val isBottomRow = index >= rowLength1
|
||||
val row = if (isBottomRow) 1 else 0
|
||||
val col = if (isBottomRow) index - rowLength1 else index
|
||||
val currentRowLength = if (isBottomRow) rowLength2 else rowLength1
|
||||
|
||||
val colSpacing = when (total) {
|
||||
2 -> 35
|
||||
3 -> 30
|
||||
4 -> 25
|
||||
else -> 23
|
||||
}
|
||||
val rowSpacing = when (total) {
|
||||
2, 3 -> 30
|
||||
4 -> 28
|
||||
else -> 25
|
||||
}
|
||||
|
||||
val totalWidth = (currentRowLength - 1) * colSpacing
|
||||
val startX = baseX - (totalWidth / 2)
|
||||
|
||||
val totalHeight = if (rowLength2 > 0) rowSpacing else 0
|
||||
var startY = baseY + 12 - (totalHeight / 2)
|
||||
|
||||
if (total >= 4) {
|
||||
startY += 8
|
||||
}
|
||||
|
||||
val posX = startX + (col * colSpacing)
|
||||
val posY = startY + (row * rowSpacing)
|
||||
|
||||
return Pair(Pair(posX, posY), scale)
|
||||
}
|
||||
|
||||
private fun playSound(soundEvent: SoundEvent): SoundInstance {
|
||||
val soundInstance = SimpleSoundInstance.forUI(soundEvent, 1.0F)
|
||||
Minecraft.getInstance().soundManager.play(soundInstance)
|
||||
@@ -557,10 +791,10 @@ class TradeGUI(
|
||||
}
|
||||
|
||||
private fun cancelTradeSound() {
|
||||
if (tradeSoundInstance !== null) Minecraft.getInstance().soundManager.stop(tradeSoundInstance)
|
||||
if (tradeSoundInstance != null) Minecraft.getInstance().soundManager.stop(tradeSoundInstance!!)
|
||||
}
|
||||
|
||||
private fun renderPokemonInfo(pokemon: Pokemon?, isOpposing: Boolean, context: GuiGraphics, x: Int, y: Int, mouseX: Int, mouseY: Int) {
|
||||
public fun renderPokemonInfo(pokemon: Pokemon?, isOpposing: Boolean, context: GuiGraphics, x: Int, y: Int, mouseX: Int, mouseY: Int) {
|
||||
if (pokemon != null) {
|
||||
val matrices = context.pose()
|
||||
// Level
|
||||
@@ -1047,4 +1281,4 @@ class TradeGUI(
|
||||
scale = SCALE
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.net.bag
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.net.ServerNetworkPacketHandler
|
||||
import com.cobblemon.mod.common.item.bag.CobblemonBagMenu
|
||||
import com.cobblemon.mod.common.net.messages.client.bag.UpdateBagMenuDataPacket
|
||||
import net.minecraft.server.MinecraftServer
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
object UpdateBagMenuDataHandler : ServerNetworkPacketHandler<UpdateBagMenuDataPacket> {
|
||||
override fun handle(packet: UpdateBagMenuDataPacket, server: MinecraftServer, player: ServerPlayer) {
|
||||
if (player.containerMenu !is CobblemonBagMenu) {
|
||||
Cobblemon.LOGGER.debug("Player {} interacted with invalid menu {}", player, player.containerMenu)
|
||||
return
|
||||
}
|
||||
|
||||
val menu = player.containerMenu as? CobblemonBagMenu ?: return
|
||||
menu.currentlySelectedCategory = packet.categoryId
|
||||
menu.scroll = packet.scroll
|
||||
menu.setupSlotsBasedOnContent()
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.net.bag
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.net.ServerNetworkPacketHandler
|
||||
import com.cobblemon.mod.common.item.bag.CobblemonBagMenu
|
||||
import com.cobblemon.mod.common.net.messages.client.bag.UseItemOnPokemonFromBagPacket
|
||||
import net.minecraft.server.MinecraftServer
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
object UseItemOnPokemonFromBagHandler: ServerNetworkPacketHandler<UseItemOnPokemonFromBagPacket> {
|
||||
override fun handle(packet: UseItemOnPokemonFromBagPacket, server: MinecraftServer, player: ServerPlayer) {
|
||||
if (player.containerMenu !is CobblemonBagMenu) {
|
||||
Cobblemon.LOGGER.debug("Player {} interacted with invalid menu {}", player, player.containerMenu)
|
||||
return
|
||||
}
|
||||
|
||||
val menu = player.containerMenu as? CobblemonBagMenu ?: return
|
||||
menu.useHeldItemOnPokemon(packet.partySlot)
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -15,9 +15,9 @@ import net.minecraft.client.Minecraft
|
||||
|
||||
object TradeAcceptanceChangedHandler : ClientNetworkPacketHandler<TradeAcceptanceChangedPacket> {
|
||||
override fun handle(packet: TradeAcceptanceChangedPacket, client: Minecraft) {
|
||||
if (CobblemonClient.trade?.myOffer?.get()?.uuid == packet.pokemonId) {
|
||||
if (CobblemonClient.trade?.myOffer?.get()?.any { it.uuid == packet.pokemonId } == true) {
|
||||
CobblemonClient.trade!!.oppositeAcceptedMyOffer.set(packet.accepted)
|
||||
} else if (CobblemonClient.trade?.oppositeOffer?.get()?.uuid == packet.pokemonId) {
|
||||
} else if (CobblemonClient.trade?.oppositeOffer?.get()?.any { it.uuid == packet.pokemonId } == true) {
|
||||
CobblemonClient.trade!!.acceptedOppositeOffer = packet.accepted
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -16,6 +16,6 @@ import net.minecraft.client.Minecraft
|
||||
object TradeCompletedHandler : ClientNetworkPacketHandler<TradeCompletedPacket> {
|
||||
override fun handle(packet: TradeCompletedPacket, client: Minecraft) {
|
||||
val trade = CobblemonClient.trade ?: return
|
||||
trade.completedEmitter.emit(packet.pokemonId1 to packet.pokemonId2)
|
||||
trade.completedEmitter.emit(packet.pokemonIds1 to packet.pokemonIds2)
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -20,7 +20,7 @@ import net.minecraft.client.Minecraft
|
||||
|
||||
object TradeStartedHandler : ClientNetworkPacketHandler<TradeStartedPacket> {
|
||||
override fun handle(packet: TradeStartedPacket, client: Minecraft) {
|
||||
Cobblemon.LOGGER.error("handle trade start from: " + packet.traderId)
|
||||
Cobblemon.LOGGER.info("Trade started with {}", packet.traderId)
|
||||
val trade = ClientTrade()
|
||||
CobblemonClient.trade = trade
|
||||
Minecraft.getInstance().setScreen(
|
||||
|
||||
+2
-2
@@ -18,9 +18,9 @@ object TradeUpdatedHandler : ClientNetworkPacketHandler<TradeUpdatedPacket> {
|
||||
val trade = CobblemonClient.trade ?: return
|
||||
|
||||
if (packet.playerId == Minecraft.getInstance().player?.uuid) {
|
||||
trade.myOffer.set(packet.pokemon)
|
||||
trade.myOffer.set(packet.pokemons)
|
||||
} else {
|
||||
trade.oppositeOffer.set(packet.pokemon)
|
||||
trade.oppositeOffer.set(packet.pokemons)
|
||||
}
|
||||
trade.oppositeAcceptedMyOffer.set(false)
|
||||
trade.acceptedOppositeOffer = false
|
||||
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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.CobblemonBakingOverrides
|
||||
import com.cobblemon.mod.common.item.bag.CobblemonBagItem
|
||||
|
||||
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.entity.RenderLayerParent
|
||||
import net.minecraft.client.renderer.entity.layers.RenderLayer
|
||||
import net.minecraft.client.renderer.texture.OverlayTexture
|
||||
import net.minecraft.world.entity.EquipmentSlot
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.ItemDisplayContext
|
||||
|
||||
class CobblemonBagRenderer<T : Player>(renderLayerParent: RenderLayerParent<T, PlayerModel<T>>): RenderLayer<T, PlayerModel<T>>(renderLayerParent) {
|
||||
override fun render(
|
||||
poseStack: PoseStack,
|
||||
bufferSource: MultiBufferSource,
|
||||
packedLight: Int,
|
||||
player: T,
|
||||
limbSwing: Float,
|
||||
limbSwingAmount: Float,
|
||||
partialTick: Float,
|
||||
ageInTicks: Float,
|
||||
netHeadYaw: Float,
|
||||
headPitch: Float
|
||||
) {
|
||||
val bagItem = player.getItemBySlot(EquipmentSlot.CHEST)
|
||||
if (bagItem.item !is CobblemonBagItem) return
|
||||
val model = CobblemonBakingOverrides.bagModels[bagItem.item]?.getModel() ?: return
|
||||
|
||||
player.level().profiler.push("cobblemon_bag_render")
|
||||
poseStack.pushPose()
|
||||
|
||||
parentModel.body.translateAndRotate(poseStack)
|
||||
|
||||
poseStack.rotateAround(Axis.ZP.rotationDegrees(180F), 0F, 1F, 0F)
|
||||
poseStack.translate(0.0, 1.0, 0.0)
|
||||
|
||||
Minecraft.getInstance().itemRenderer.render(
|
||||
bagItem,
|
||||
ItemDisplayContext.FIXED,
|
||||
false,
|
||||
poseStack,
|
||||
bufferSource,
|
||||
packedLight,
|
||||
OverlayTexture.NO_OVERLAY,
|
||||
model
|
||||
)
|
||||
|
||||
poseStack.popPose()
|
||||
player.level().profiler.pop()
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -29,8 +29,8 @@ class FarfetchdGalarianModel(root: ModelPart) : PokemonPosableModel(root), Heade
|
||||
override var portraitScale = 2.6F
|
||||
override var portraitTranslation = Vec3(-0.2, -1.0, 0.0)
|
||||
|
||||
override var profileScale = 1.1F
|
||||
override var profileTranslation = Vec3(-0.1, 0.1, 0.0)
|
||||
override var profileScale = 0.93F
|
||||
override var profileTranslation = Vec3(-0.1, 0.36, 0.0)
|
||||
|
||||
lateinit var standing: Pose
|
||||
lateinit var walk: Pose
|
||||
|
||||
+2
-2
@@ -28,8 +28,8 @@ class FarfetchdModel(root: ModelPart) : PokemonPosableModel(root), HeadedFrame,
|
||||
override var portraitScale = 2.6F
|
||||
override var portraitTranslation = Vec3(-0.2, -1.0, 0.0)
|
||||
|
||||
override var profileScale = 1.1F
|
||||
override var profileTranslation = Vec3(-0.1, 0.1, 0.0)
|
||||
override var profileScale = 0.93F
|
||||
override var profileTranslation = Vec3(-0.1, 0.36, 0.0)
|
||||
|
||||
lateinit var standing: Pose
|
||||
lateinit var walk: Pose
|
||||
|
||||
+2
-2
@@ -23,8 +23,8 @@ class KabutoModel(root: ModelPart) : PokemonPosableModel(root) {
|
||||
override var portraitScale = 3.3F
|
||||
override var portraitTranslation = Vec3(0.0, -3.3, 0.0)
|
||||
|
||||
override var profileScale = 1.6F
|
||||
override var profileTranslation = Vec3(0.0, -0.6, 0.0)
|
||||
override var profileScale = 1.25F
|
||||
override var profileTranslation = Vec3(0.0, -0.17, 0.0)
|
||||
|
||||
lateinit var standing: CobblemonPose
|
||||
lateinit var walk: CobblemonPose
|
||||
|
||||
+2
-2
@@ -21,8 +21,8 @@ class HoothootModel (root: ModelPart) : PokemonPosableModel(root) {
|
||||
|
||||
override var portraitScale = 2.2F
|
||||
override var portraitTranslation = Vec3(-0.25, -0.9, 0.0)
|
||||
override var profileScale = 1.0F
|
||||
override var profileTranslation = Vec3(0.0, 0.3, 0.0)
|
||||
override var profileScale = 0.82F
|
||||
override var profileTranslation = Vec3(0.0, 0.53, 0.0)
|
||||
|
||||
lateinit var standing: Pose
|
||||
lateinit var walk: Pose
|
||||
|
||||
+2
-2
@@ -29,8 +29,8 @@ class WooperModel(root: ModelPart) : PokemonPosableModel(root), HeadedFrame {
|
||||
override var portraitScale = 2.0F
|
||||
override var portraitTranslation = Vec3(-0.15, -0.65, 0.0)
|
||||
|
||||
override var profileScale = 0.9F
|
||||
override var profileTranslation = Vec3(0.0, 0.4, 0.0)
|
||||
override var profileScale = 0.75F
|
||||
override var profileTranslation = Vec3(0.0, 0.6, 0.0)
|
||||
|
||||
lateinit var shoulderLeft: Pose
|
||||
lateinit var shoulderRight: Pose
|
||||
|
||||
+2
-2
@@ -29,8 +29,8 @@ class WooperPaldeanModel(root: ModelPart) : PokemonPosableModel(root), HeadedFra
|
||||
override var portraitScale = 2.0F
|
||||
override var portraitTranslation = Vec3(-0.15, -0.65, 0.0)
|
||||
|
||||
override var profileScale = 0.9F
|
||||
override var profileTranslation = Vec3(0.0, 0.4, 0.0)
|
||||
override var profileScale = 0.75F
|
||||
override var profileTranslation = Vec3(0.0, 0.6, 0.0)
|
||||
|
||||
lateinit var shoulderLeft: Pose
|
||||
lateinit var shoulderRight: Pose
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ class DusclopsModel (root: ModelPart) : PokemonPosableModel(root) {
|
||||
lateinit var battleidle: Pose
|
||||
|
||||
override fun registerPoses() {
|
||||
animations["cry"] = "q.bedrock_stateful('squirtle', 'cry')".asExpressionLike()
|
||||
animations["cry"] = "q.bedrock_stateful('dusclops', 'cry')".asExpressionLike()
|
||||
|
||||
val blink = quirk { bedrockStateful("dusclops", "blink") }
|
||||
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ class CarbinkModel (root: ModelPart) : PokemonPosableModel(root) {
|
||||
override var portraitScale = 1.8F
|
||||
override var portraitTranslation = Vec3(0.0, 0.2, 0.0)
|
||||
|
||||
override var profileScale = 0.85F
|
||||
override var profileScale = 0.68F
|
||||
override var profileTranslation = Vec3(0.0, 0.7, 0.0)
|
||||
|
||||
lateinit var standing: CobblemonPose
|
||||
|
||||
+2
-2
@@ -26,8 +26,8 @@ class ScatterbugModel (root: ModelPart) : PokemonPosableModel(root), HeadedFrame
|
||||
override var portraitScale = 2.6F
|
||||
override var portraitTranslation = Vec3(-0.2, -1.9, 0.0)
|
||||
|
||||
override var profileScale = 1.2F
|
||||
override var profileTranslation = Vec3(0.0, 0.05, 0.0)
|
||||
override var profileScale = 0.98F
|
||||
override var profileTranslation = Vec3(0.0, 0.28, 0.0)
|
||||
|
||||
lateinit var standing: CobblemonPose
|
||||
lateinit var walk: CobblemonPose
|
||||
|
||||
+2
-2
@@ -36,8 +36,8 @@ class CharcadetModel(root: ModelPart) : PokemonPosableModel(root), HeadedFrame,
|
||||
override var portraitScale = 1.7F
|
||||
override var portraitTranslation = Vec3(-0.15, 0.08, 0.0)
|
||||
|
||||
override var profileScale = 0.8F
|
||||
override var profileTranslation = Vec3(0.0, 0.6, 0.0)
|
||||
override var profileScale = 0.58F
|
||||
override var profileTranslation = Vec3(0.0, 0.91, 0.0)
|
||||
|
||||
lateinit var standing: CobblemonPose
|
||||
lateinit var walking: CobblemonPose
|
||||
|
||||
+2
-2
@@ -35,8 +35,8 @@ class QuaquavalModel (root: ModelPart) : PokemonPosableModel(root), HeadedFrame,
|
||||
override var portraitScale = 2.3F
|
||||
override var portraitTranslation = Vec3(-0.42, 3.7, 0.0)
|
||||
|
||||
override var profileScale = 0.32F
|
||||
override var profileTranslation = Vec3(0.0, 1.24, 0.0)
|
||||
override var profileScale = 0.36F
|
||||
override var profileTranslation = Vec3(0.0, 1.19, 0.0)
|
||||
|
||||
lateinit var standing: CobblemonPose
|
||||
lateinit var standing2: CobblemonPose
|
||||
|
||||
-208
@@ -1,208 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen9
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.animation.WingFlapIdleAnimation
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.createTransformation
|
||||
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.util.math.geometry.toRadians
|
||||
import net.minecraft.client.model.geom.ModelPart
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
class SquawkabillyModel (root: ModelPart) : PokemonPosableModel(root), HeadedFrame, BipedFrame, BiWingedFrame {
|
||||
override val rootPart = root.registerChildWithAllChildren("squawkabilly")
|
||||
override val head = getPart("head")
|
||||
override val leftWing = getPart("wing_left")
|
||||
override val rightWing = getPart("wing_right")
|
||||
override val leftLeg = getPart("leg_left")
|
||||
override val rightLeg = getPart("leg_right")
|
||||
private val tail = getPart("tail")
|
||||
|
||||
override var portraitScale = 2.0F
|
||||
override var portraitTranslation = Vec3(-0.2, -0.2, 0.0)
|
||||
|
||||
override var profileScale = 0.85F
|
||||
override var profileTranslation = Vec3(0.0, 0.51, 0.0)
|
||||
|
||||
lateinit var standing: Pose
|
||||
lateinit var walk: Pose
|
||||
lateinit var hovering: Pose
|
||||
lateinit var flying: Pose
|
||||
lateinit var shoulderLeft: Pose
|
||||
lateinit var shoulderRight: Pose
|
||||
|
||||
override val cryAnimation = CryProvider { bedrockStateful("squawkabilly", "cry") }
|
||||
|
||||
val shoulderOffsetX = -1.0
|
||||
val shoulderOffsetY = 0
|
||||
override fun registerPoses() {
|
||||
val blink = quirk { bedrockStateful("squawkabilly", "blink") }
|
||||
|
||||
standing = registerPose(
|
||||
poseName = "standing",
|
||||
quirks = arrayOf(blink),
|
||||
poseTypes = PoseType.UI_POSES + PoseType.STAND,
|
||||
transformTicks = 10,
|
||||
animations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("squawkabilly", "ground_idle")
|
||||
)
|
||||
)
|
||||
|
||||
walk = registerPose(
|
||||
poseName = "walk",
|
||||
quirks = arrayOf(blink),
|
||||
poseType = PoseType.WALK,
|
||||
transformTicks = 10,
|
||||
animations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("squawkabilly", "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 },
|
||||
),
|
||||
)
|
||||
)
|
||||
|
||||
hovering = registerPose(
|
||||
poseName = "hovering",
|
||||
quirks = arrayOf(blink),
|
||||
poseTypes = setOf(PoseType.FLOAT, PoseType.HOVER),
|
||||
transformTicks = 10,
|
||||
animations = arrayOf(
|
||||
singleBoneLook(),
|
||||
WingFlapIdleAnimation(this,
|
||||
flapFunction = sineFunction(verticalShift = -10F.toRadians(), period = 0.9F, amplitude = 0.9F),
|
||||
timeVariable = { state, _, _ -> state.animationSeconds },
|
||||
axis = ModelPartTransformation.Z_AXIS
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
flying = registerPose(
|
||||
poseName = "flying",
|
||||
quirks = arrayOf(blink),
|
||||
poseTypes = setOf(PoseType.FLY, PoseType.SWIM),
|
||||
transformTicks = 10,
|
||||
animations = arrayOf(
|
||||
singleBoneLook(),
|
||||
WingFlapIdleAnimation(this,
|
||||
flapFunction = sineFunction(verticalShift = -14F.toRadians(), period = 0.9F, amplitude = 0.9F),
|
||||
timeVariable = { state, _, _ -> state.animationSeconds },
|
||||
axis = ModelPartTransformation.Z_AXIS
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
shoulderLeft = registerPose(
|
||||
poseType = PoseType.SHOULDER_LEFT,
|
||||
quirks = arrayOf(blink),
|
||||
animations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("squawkabilly", "ground_idle")
|
||||
),
|
||||
transformedParts = arrayOf(
|
||||
rootPart.createTransformation().addPosition(shoulderOffsetX, shoulderOffsetY, 0.0)
|
||||
)
|
||||
)
|
||||
|
||||
shoulderRight = registerPose(
|
||||
poseType = PoseType.SHOULDER_RIGHT,
|
||||
quirks = arrayOf(blink),
|
||||
animations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("squawkabilly", "ground_idle")
|
||||
),
|
||||
transformedParts = arrayOf(
|
||||
rootPart.createTransformation().addPosition(-shoulderOffsetX, shoulderOffsetY, 0.0)
|
||||
)
|
||||
)
|
||||
|
||||
}
|
||||
// override fun getFaintAnimation(
|
||||
// pokemonEntity: PokemonEntity,
|
||||
// state: PosableState<PokemonEntity>
|
||||
// ) = if (state.isNotPosedIn(sleep)) bedrockStateful("squawkabilly", "faint") else null
|
||||
}
|
||||
-1
@@ -397,7 +397,6 @@ object VaryingModelRepository {
|
||||
inbuilt("bunnelby", ::BunnelbyModel)
|
||||
inbuilt("arrokuda", ::ArrokudaModel)
|
||||
inbuilt("barraskewda", ::BarraskewdaModel)
|
||||
inbuilt("squawkabilly", ::SquawkabillyModel)
|
||||
inbuilt("ponyta_galarian", ::PonytaGalarianModel)
|
||||
inbuilt("rapidash_galarian", ::RapidashGalarianModel)
|
||||
inbuilt("volbeat", ::VolbeatModel)
|
||||
|
||||
@@ -14,12 +14,12 @@ import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import java.util.UUID
|
||||
|
||||
class ClientTrade {
|
||||
var myOffer = SettableObservable<Pokemon?>(null)
|
||||
var oppositeOffer = SettableObservable<Pokemon?>(null)
|
||||
var myOffer = SettableObservable<List<Pokemon>>(emptyList())
|
||||
var oppositeOffer = SettableObservable<List<Pokemon>>(emptyList())
|
||||
var tradeProcessing = SettableObservable(Pair(false, false))
|
||||
var oppositeAcceptedMyOffer = SettableObservable(false)
|
||||
var acceptedOppositeOffer = false
|
||||
|
||||
var completedEmitter = SimpleObservable<Pair<UUID, UUID>>()
|
||||
var completedEmitter = SimpleObservable<Pair<List<UUID>, List<UUID>>>()
|
||||
var cancelEmitter = SimpleObservable<Unit>()
|
||||
}
|
||||
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.data
|
||||
import com.cobblemon.mod.common.*
|
||||
import com.cobblemon.mod.common.Cobblemon.LOGGER
|
||||
import com.cobblemon.mod.common.api.abilities.Abilities
|
||||
import com.cobblemon.mod.common.api.bag.BagCategories
|
||||
import com.cobblemon.mod.common.api.berry.Berries
|
||||
import com.cobblemon.mod.common.api.cooking.Seasonings
|
||||
import com.cobblemon.mod.common.api.data.DataProvider
|
||||
@@ -120,6 +121,7 @@ object CobblemonDataProvider : DataProvider {
|
||||
this.register(SpawnBaitEffects, reloadable = false)
|
||||
this.register(CobblemonRideSettings, reloadable = true)
|
||||
this.register(TechnicalMachines, reloadable = false)
|
||||
this.register(BagCategories, reloadable = false)
|
||||
SpawnBait.Effects.setupEffects()
|
||||
|
||||
PlatformEvents.SERVER_PLAYER_LOGOUT.subscribe {
|
||||
|
||||
-1
@@ -160,5 +160,4 @@ class CobblemonChestBoatEntity(entityType: EntityType<CobblemonChestBoatEntity>,
|
||||
private const val INVENTORY_SLOTS = 27
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2744,4 +2744,9 @@ open class PokemonEntity(
|
||||
}
|
||||
|
||||
fun hasRider() = this.passengers.any { it is LivingEntity }
|
||||
}
|
||||
|
||||
override fun playStepSound(pos: BlockPos, state: BlockState) {
|
||||
if (this.pokemon.species.silenceStepSounds) return
|
||||
super.playStepSound(pos, state)
|
||||
}
|
||||
}
|
||||
@@ -31,6 +31,7 @@ import net.minecraft.world.item.BlockItem
|
||||
import com.cobblemon.mod.common.platform.events.ServerPlayerEvent
|
||||
import com.cobblemon.mod.common.api.storage.player.PlayerInstancedDataStoreTypes
|
||||
import com.cobblemon.mod.common.item.GemItem
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.platform.events.PlatformEvents
|
||||
import com.cobblemon.mod.common.util.effectiveName
|
||||
import com.cobblemon.mod.common.util.getPlayer
|
||||
@@ -164,26 +165,21 @@ object AdvancementHandler : EventHandler {
|
||||
}
|
||||
|
||||
fun onTradeCompleted(event : TradeEvent.Post) {
|
||||
val player1 = event.tradeParticipant1Pokemon.getOwnerPlayer()
|
||||
val player2 = event.tradeParticipant2Pokemon.getOwnerPlayer()
|
||||
if (player1 != null) {
|
||||
CobblemonCriteria.TRADE_POKEMON.trigger(player1, TradePokemonContext(event.tradeParticipant1Pokemon, event.tradeParticipant2Pokemon))
|
||||
val playerData = Cobblemon.playerDataManager.getGenericData(player1)
|
||||
val advancementData = playerData.advancementData
|
||||
advancementData.updateTotalTradedCount()
|
||||
advancementData.updateAspectsCollected(player1, event.tradeParticipant2Pokemon)
|
||||
CobblemonCriteria.COLLECT_ASPECT.trigger(player1, advancementData.aspectsCollected)
|
||||
Cobblemon.playerDataManager.saveSingle(playerData, PlayerInstancedDataStoreTypes.GENERAL)
|
||||
}
|
||||
if (player2 != null) {
|
||||
CobblemonCriteria.TRADE_POKEMON.trigger(player2, TradePokemonContext(event.tradeParticipant2Pokemon, event.tradeParticipant1Pokemon))
|
||||
val playerData = Cobblemon.playerDataManager.getGenericData(player2)
|
||||
val advancementData = playerData.advancementData
|
||||
advancementData.updateTotalTradedCount()
|
||||
advancementData.updateAspectsCollected(player2, event.tradeParticipant1Pokemon)
|
||||
CobblemonCriteria.COLLECT_ASPECT.trigger(player2, advancementData.aspectsCollected)
|
||||
Cobblemon.playerDataManager.saveSingle(playerData, PlayerInstancedDataStoreTypes.GENERAL)
|
||||
onTradeCompleted(event.tradeParticipant1Pokemon, event.tradeParticipant2Pokemon)
|
||||
onTradeCompleted(event.tradeParticipant2Pokemon, event.tradeParticipant1Pokemon)
|
||||
}
|
||||
|
||||
private fun onTradeCompleted(received: List<Pokemon>, traded: List<Pokemon>) {
|
||||
val player = received.firstOrNull()?.getOwnerPlayer() ?: return
|
||||
received.forEach { receivedPokemon ->
|
||||
traded.forEach { tradedPokemon -> CobblemonCriteria.TRADE_POKEMON.trigger(player, TradePokemonContext(tradedPokemon, receivedPokemon)) }
|
||||
}
|
||||
val playerData = Cobblemon.playerDataManager.getGenericData(player)
|
||||
val advancementData = playerData.advancementData
|
||||
advancementData.updateTotalTradedCount()
|
||||
received.forEach { advancementData.updateAspectsCollected(player, it) }
|
||||
CobblemonCriteria.COLLECT_ASPECT.trigger(player, advancementData.aspectsCollected)
|
||||
Cobblemon.playerDataManager.saveSingle(playerData, PlayerInstancedDataStoreTypes.GENERAL)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -110,8 +110,8 @@ object StatHandler : EventHandler {
|
||||
}
|
||||
|
||||
fun onTradeCompleted(event : TradeEvent.Post) {
|
||||
event.tradeParticipant1Pokemon.getOwnerPlayer()?.awardStat(getStat(Cobblemon.statistics.TRADED))
|
||||
event.tradeParticipant2Pokemon.getOwnerPlayer()?.awardStat(getStat(Cobblemon.statistics.TRADED))
|
||||
event.tradeParticipant1Pokemon.firstOrNull()?.getOwnerPlayer()?.awardStat(getStat(Cobblemon.statistics.TRADED))
|
||||
event.tradeParticipant2Pokemon.firstOrNull()?.getOwnerPlayer()?.awardStat(getStat(Cobblemon.statistics.TRADED))
|
||||
}
|
||||
|
||||
fun onFossilRevived(event : FossilRevivedEvent) {
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.item.bag
|
||||
|
||||
import net.minecraft.core.HolderLookup
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.nbt.ListTag
|
||||
import net.minecraft.world.Container
|
||||
import net.minecraft.world.ContainerHelper
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import kotlin.math.min
|
||||
|
||||
class CobblemonBagContainer: Container {
|
||||
val items: MutableList<ItemStack> = mutableListOf()
|
||||
|
||||
override fun getContainerSize(): Int {
|
||||
return items.size
|
||||
}
|
||||
|
||||
override fun getItem(slot: Int): ItemStack {
|
||||
if (slot >= items.size) return ItemStack.EMPTY
|
||||
return items[slot]
|
||||
}
|
||||
|
||||
override fun isEmpty(): Boolean {
|
||||
return items.isEmpty()
|
||||
}
|
||||
|
||||
override fun removeItem(slot: Int, amount: Int): ItemStack {
|
||||
if (slot >= items.size) return ItemStack.EMPTY
|
||||
val itemStack = items[slot].split(amount)
|
||||
if (items[slot].isEmpty) {
|
||||
items.removeAt(slot)
|
||||
}
|
||||
return itemStack
|
||||
}
|
||||
|
||||
override fun removeItemNoUpdate(slot: Int): ItemStack { return ItemStack.EMPTY }
|
||||
|
||||
override fun clearContent() {
|
||||
items.clear()
|
||||
setChanged()
|
||||
}
|
||||
|
||||
override fun setChanged() {
|
||||
}
|
||||
|
||||
override fun setItem(slot: Int, stack: ItemStack) {} // Obsolete
|
||||
|
||||
override fun stillValid(player: Player): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun getMaxStackSize(): Int {
|
||||
return 99999
|
||||
}
|
||||
|
||||
fun fromTag(tag: ListTag, levelRegistry: HolderLookup.Provider) {
|
||||
items.clear()
|
||||
|
||||
tag.forEach {
|
||||
val compoundTag = it as CompoundTag
|
||||
val count = compoundTag.getInt("count")
|
||||
compoundTag.putInt("count", 1)
|
||||
val item = ItemStack.parse(levelRegistry, it)
|
||||
item.ifPresent { theItem ->
|
||||
theItem.count = count
|
||||
items.add(theItem)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun createTag(levelRegistry: HolderLookup.Provider): ListTag {
|
||||
val tag = ListTag()
|
||||
|
||||
items.forEach {
|
||||
val fakeItem = it.copyWithCount(1)
|
||||
val compoundTag = fakeItem.save(levelRegistry) as CompoundTag
|
||||
compoundTag.putInt("count", it.count) // ItemStack does not save count above 99 for some reason, so we save it ourselves
|
||||
tag.add(compoundTag)
|
||||
}
|
||||
|
||||
return tag
|
||||
}
|
||||
|
||||
fun dropAll(player: Player) {
|
||||
items.forEach {
|
||||
player.drop(it, true, false)
|
||||
}
|
||||
items.clear()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.item.bag
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.item.CobblemonItem
|
||||
import com.cobblemon.mod.common.bag.BagEntity
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.resources.sounds.SimpleSoundInstance
|
||||
import net.minecraft.core.Holder
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.sounds.SoundEvent
|
||||
import net.minecraft.world.InteractionHand
|
||||
import net.minecraft.world.InteractionResultHolder
|
||||
import net.minecraft.world.MenuProvider
|
||||
import net.minecraft.world.entity.EquipmentSlot
|
||||
import net.minecraft.world.entity.player.Inventory
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu
|
||||
import net.minecraft.world.item.Equipable
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.level.Level
|
||||
|
||||
class CobblemonBagItem: CobblemonItem(Properties().stacksTo(1)), MenuProvider, Equipable {
|
||||
override fun use(level: Level, player: Player, usedHand: InteractionHand): InteractionResultHolder<ItemStack?> {
|
||||
val itemStack = player.getItemInHand(usedHand)
|
||||
player.openMenu(this)
|
||||
return InteractionResultHolder.success(itemStack)
|
||||
}
|
||||
|
||||
override fun createMenu(i: Int, inventory: Inventory, player: Player): AbstractContainerMenu {
|
||||
val bagEntity = (player as? BagEntity)
|
||||
val container = bagEntity?.`cobblemon$getBagContainer`() ?: CobblemonBagContainer()
|
||||
|
||||
return CobblemonBagMenu(i, inventory, container)
|
||||
}
|
||||
|
||||
override fun getDisplayName(): Component? {
|
||||
return Component.translatable("cobblemon.container.bag")
|
||||
}
|
||||
|
||||
override fun getEquipmentSlot(): EquipmentSlot = EquipmentSlot.CHEST
|
||||
|
||||
override fun getEquipSound(): Holder<SoundEvent?>? {
|
||||
Minecraft.getInstance().soundManager.play(SimpleSoundInstance.forUI(CobblemonSounds.ITEM_BAG_EQUIP, 1.0F))
|
||||
return null
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,428 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.item.bag
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonMenuType
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.advancement.CobblemonCriteria
|
||||
import com.cobblemon.mod.common.advancement.criterion.PokemonInteractContext
|
||||
import com.cobblemon.mod.common.api.bag.BagCategories
|
||||
import com.cobblemon.mod.common.api.item.PokemonSelectingItem
|
||||
import com.cobblemon.mod.common.api.storage.party.PartyStore
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.util.isInBattle
|
||||
import net.minecraft.CrashReport
|
||||
import net.minecraft.ReportedException
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.resources.sounds.SimpleSoundInstance
|
||||
import net.minecraft.core.NonNullList
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.sounds.SoundEvent
|
||||
import net.minecraft.world.InteractionResult
|
||||
import net.minecraft.world.SimpleContainer
|
||||
import net.minecraft.world.entity.player.Inventory
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.inventory.AbstractContainerMenu
|
||||
import net.minecraft.world.inventory.ClickAction
|
||||
import net.minecraft.world.inventory.ClickType
|
||||
import net.minecraft.world.inventory.Slot
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import kotlin.math.ceil
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
class CobblemonBagMenu: AbstractContainerMenu {
|
||||
companion object {
|
||||
val BAG_SLOTS = 0..31
|
||||
private val PARTY_SLOTS = 32..37
|
||||
private val INVENTORY_SLOTS = 38..64
|
||||
private val HOTBAR_SLOTS = 65..73
|
||||
}
|
||||
|
||||
private val playerInventory: Inventory
|
||||
private val bagContainer: CobblemonBagContainer
|
||||
private val partyContainer: SimpleContainer
|
||||
|
||||
private var serverParty: PartyStore? = null
|
||||
var currentlySelectedCategory = -1
|
||||
var scroll = 0
|
||||
var maxScroll = 0
|
||||
var categoryItemCounts = mutableListOf<Int>()
|
||||
|
||||
constructor(containerId: Int, playerInventory: Inventory): super(CobblemonMenuType.COBBLEMON_BAG, containerId) {
|
||||
this.playerInventory = playerInventory
|
||||
this.bagContainer = CobblemonBagContainer()
|
||||
this.partyContainer = SimpleContainer(6)
|
||||
for (i in 0..<BagCategories.getOrderedCategoriesList().size) { //Pre-init so Screen does not crash
|
||||
categoryItemCounts.add(0)
|
||||
}
|
||||
initializeSlots(playerInventory)
|
||||
}
|
||||
|
||||
constructor(containerId: Int, playerInventory: Inventory, bagContainer: CobblemonBagContainer): super(CobblemonMenuType.COBBLEMON_BAG, containerId) {
|
||||
this.playerInventory = playerInventory
|
||||
this.bagContainer = bagContainer
|
||||
this.partyContainer = SimpleContainer(6)
|
||||
this.serverParty = Cobblemon.storage.getParty(playerInventory.player as ServerPlayer)
|
||||
initializeSlots(playerInventory)
|
||||
setupSlotsBasedOnContent()
|
||||
calculateCategoriesItemCounts()
|
||||
}
|
||||
|
||||
private fun initializeSlots(playerInventory: Inventory) {
|
||||
for ((index, _) in BAG_SLOTS.withIndex()) {
|
||||
val i = index / 8
|
||||
val j = index % 8
|
||||
addSlot(CobblemonBagSlot(bagContainer, -1, 81 + j * 18, 50 + i * 18))
|
||||
}
|
||||
|
||||
for ((index, _) in PARTY_SLOTS.withIndex()) {
|
||||
val xPos = 46
|
||||
val yPos = 32 + 33 * index
|
||||
if (serverParty != null) {
|
||||
addSlot(CobblemonBagPartySlot(partyContainer, index,
|
||||
{ serverParty?.get(index) != null },
|
||||
{ serverParty?.get(index)?.heldItem() ?: ItemStack.EMPTY },
|
||||
xPos, yPos))
|
||||
} else {
|
||||
addSlot(CobblemonBagPartySlot(partyContainer, index,
|
||||
{ CobblemonClient.storage.party.get(index) != null },
|
||||
{ CobblemonClient.storage.party.get(index)?.heldItem() ?: ItemStack.EMPTY },
|
||||
xPos, yPos))
|
||||
}
|
||||
}
|
||||
|
||||
for ((index, _) in INVENTORY_SLOTS.withIndex()) {
|
||||
val i = index / 9
|
||||
val j = index % 9
|
||||
addSlot(Slot(playerInventory, 9 + index, 81 + j * 18, 142 + i * 18))
|
||||
}
|
||||
|
||||
for ((index, _) in HOTBAR_SLOTS.withIndex()) {
|
||||
addSlot(Slot(playerInventory, index, 81 + index * 18, 200))
|
||||
}
|
||||
}
|
||||
|
||||
fun setupSlotsBasedOnContent() {
|
||||
BAG_SLOTS.forEach {
|
||||
(getSlot(it) as CobblemonBagSlot).let {
|
||||
it.simulatedSlot = -1
|
||||
it.slotOverflowValue = 0
|
||||
}
|
||||
}
|
||||
|
||||
var slotId = BAG_SLOTS.first - 8 * scroll
|
||||
bagContainer.items.forEachIndexed { index, itemStack ->
|
||||
if (currentlySelectedCategory == -1 || BagCategories.getOrderedCategoriesList()[currentlySelectedCategory].itemIsValid(itemStack)) {
|
||||
val stackCount = ceil(itemStack.count.toFloat() / itemStack.maxStackSize).toInt()
|
||||
for (i in 0..<stackCount) {
|
||||
if (slotId in BAG_SLOTS) {
|
||||
val slot = getSlot(slotId) as CobblemonBagSlot
|
||||
slot.simulatedSlot = index
|
||||
slot.slotOverflowValue = i
|
||||
}
|
||||
slotId += 1
|
||||
if (slotId > BAG_SLOTS.last) return@forEachIndexed
|
||||
}
|
||||
}
|
||||
}
|
||||
updateMaxScroll()
|
||||
}
|
||||
|
||||
fun calculateCategoriesItemCounts() {
|
||||
val orderedCategories = BagCategories.getOrderedCategoriesList()
|
||||
categoryItemCounts.clear()
|
||||
for (i in 0..<orderedCategories.size) {
|
||||
categoryItemCounts.add(0)
|
||||
}
|
||||
|
||||
bagContainer.items.forEach { itemStack ->
|
||||
for (i in 0..<orderedCategories.size) {
|
||||
val category = orderedCategories[i]
|
||||
if (category.itemIsValid(itemStack)) {
|
||||
categoryItemCounts[i] += itemStack.count
|
||||
return@forEach
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun changeCategory(categoryId: Int) {
|
||||
currentlySelectedCategory = categoryId
|
||||
scroll = 0
|
||||
setupSlotsBasedOnContent()
|
||||
}
|
||||
|
||||
fun updateMaxScroll() {
|
||||
var itemCount = 0
|
||||
bagContainer.items.forEach { itemStack ->
|
||||
if (currentlySelectedCategory == -1 || BagCategories.getOrderedCategoriesList()[currentlySelectedCategory].itemIsValid(itemStack)) {
|
||||
itemCount += ceil(itemStack.count.toFloat() / itemStack.maxStackSize).toInt()
|
||||
}
|
||||
}
|
||||
val rowsWithItems = (itemCount - 1) / 8 + 1
|
||||
maxScroll = max(rowsWithItems - 3, 0)
|
||||
}
|
||||
|
||||
override fun stillValid(player: Player): Boolean {
|
||||
return true //Add some extra logic like checking for maybe bag item existance
|
||||
}
|
||||
|
||||
override fun sendAllDataToRemote() { //We want to send more info than just the slots
|
||||
val items = NonNullList.create<ItemStack>()
|
||||
for (i in PARTY_SLOTS.first..HOTBAR_SLOTS.last) {
|
||||
this.remoteSlots[i] = this.slots[i].item.copy()
|
||||
items.add(this.remoteSlots[i].copy())
|
||||
}
|
||||
|
||||
this.remoteCarried = this.carried.copy()
|
||||
|
||||
bagContainer.items.forEach {
|
||||
items.add(it.copy())
|
||||
}
|
||||
|
||||
if (this.synchronizer != null) {
|
||||
this.synchronizer!!.sendInitialData(this, items, this.remoteCarried, this.remoteDataSlots.toIntArray())
|
||||
}
|
||||
}
|
||||
|
||||
override fun initializeContents(stateId: Int, items: List<ItemStack>, carried: ItemStack) {
|
||||
bagContainer.items.clear()
|
||||
items.forEachIndexed { index, stack ->
|
||||
val adjustedIndex = index + PARTY_SLOTS.first
|
||||
if (adjustedIndex in PARTY_SLOTS.first..HOTBAR_SLOTS.last) {
|
||||
this.slots[adjustedIndex].set(stack)
|
||||
} else {
|
||||
bagContainer.items.add(stack)
|
||||
}
|
||||
}
|
||||
|
||||
this.carried = carried
|
||||
this.stateId = stateId
|
||||
setupSlotsBasedOnContent()
|
||||
calculateCategoriesItemCounts()
|
||||
}
|
||||
|
||||
override fun clicked(slotId: Int, button: Int, clickType: ClickType, player: Player) {
|
||||
if (slotId in BAG_SLOTS) {
|
||||
try {
|
||||
doBagClick(slotId, button, clickType, player)
|
||||
} catch (exception: Exception) {
|
||||
val crashReport = CrashReport.forThrowable(exception, "Container click")
|
||||
val crashReportCategory = crashReport.addCategory("Click info")
|
||||
crashReportCategory.setDetail("Menu Type") {
|
||||
if (this.menuType != null) BuiltInRegistries.MENU.getKey(this.menuType!!)
|
||||
.toString() else "<no type>"
|
||||
}
|
||||
crashReportCategory.setDetail("Menu Class") { this.javaClass.getCanonicalName() }
|
||||
crashReportCategory.setDetail("Slot Count", this.slots.size)
|
||||
crashReportCategory.setDetail("Slot", slotId)
|
||||
crashReportCategory.setDetail("Button", button)
|
||||
crashReportCategory.setDetail("Type", clickType)
|
||||
throw ReportedException(crashReport)
|
||||
}
|
||||
return
|
||||
} else if (slotId in PARTY_SLOTS) {
|
||||
onPartySlotClick(slotId, button, clickType, player)
|
||||
}
|
||||
super.clicked(slotId, button, clickType, player)
|
||||
}
|
||||
|
||||
// We handle the bag slots completely differently than normal slots, but a lot of default logic is cut
|
||||
private fun doBagClick(slotId: Int, button: Int, clickType: ClickType, player: Player) {
|
||||
val slot = (getSlot(slotId) as? CobblemonBagSlot) ?: return
|
||||
val slotItem = slot.item
|
||||
|
||||
if (clickType == ClickType.PICKUP && (button == 0 || button == 1)) {
|
||||
val primaryButton = if (button == 0) ClickAction.PRIMARY else ClickAction.SECONDARY
|
||||
val carriedStack = carried
|
||||
|
||||
if (carriedStack.isEmpty) {
|
||||
if (!slotItem.isEmpty) {
|
||||
val pickupCount = if (primaryButton == ClickAction.PRIMARY) slotItem.count else (slotItem.count + 1) / 2
|
||||
|
||||
val removedItemStack = slot.remove(pickupCount)
|
||||
if (!removedItemStack.isEmpty) {
|
||||
carried = removedItemStack
|
||||
slot.onTake(player, removedItemStack)
|
||||
getAndReduceCategoryCount(removedItemStack)
|
||||
}
|
||||
|
||||
playSound(CobblemonSounds.ITEM_BAG_ITEM_OUT)
|
||||
setupSlotsBasedOnContent()
|
||||
}
|
||||
} else {
|
||||
val (categoryId, allowedTransfer) = calculateInsertCount(carriedStack)
|
||||
if (allowedTransfer <= 0) return
|
||||
|
||||
val transferCount = if (primaryButton == ClickAction.PRIMARY) min(carriedStack.count, allowedTransfer) else 1
|
||||
|
||||
bagContainer.items.forEachIndexed { index, slotStack ->
|
||||
if (ItemStack.isSameItemSameComponents(carriedStack, slotStack) && !tryItemClickBehaviourOverride(player, primaryButton, CobblemonBagSlot(bagContainer, index, 0, 0), slotStack, carriedStack)
|
||||
) { // Provide a slot with index equal to the item, as there is not really any 'real' slots
|
||||
slotStack.grow(transferCount)
|
||||
carriedStack.shrink(transferCount)
|
||||
categoryItemCounts[categoryId] += transferCount
|
||||
playSound(CobblemonSounds.ITEM_BAG_ITEM_IN)
|
||||
setupSlotsBasedOnContent()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
val transferItem = carriedStack.split(transferCount)
|
||||
bagContainer.items.add(transferItem)
|
||||
categoryItemCounts[categoryId] += transferCount
|
||||
playSound(CobblemonSounds.ITEM_BAG_ITEM_IN)
|
||||
setupSlotsBasedOnContent()
|
||||
}
|
||||
} else if (clickType == ClickType.QUICK_MOVE && (button == 0 || button == 1)) {
|
||||
quickMoveStackFromBag(player, slot)
|
||||
} else if (clickType == ClickType.CLONE && player.hasInfiniteMaterials() && carried.isEmpty && !slotItem.isEmpty) {
|
||||
carried = slotItem.copyWithCount(slotItem.maxStackSize)
|
||||
} else if (clickType == ClickType.THROW && carried.isEmpty && !slotItem.isEmpty) {
|
||||
val throwCount = if (button == 0) 1 else min(slotItem.count, slotItem.maxStackSize)
|
||||
val bagSize = bagContainer.items.size
|
||||
val removedItemStack = slot.remove(throwCount)
|
||||
player.drop(removedItemStack, true)
|
||||
playSound(CobblemonSounds.ITEM_BAG_ITEM_OUT)
|
||||
getAndReduceCategoryCount(removedItemStack)
|
||||
|
||||
if (bagSize != bagContainer.items.size) {
|
||||
setupSlotsBasedOnContent()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Handle party slot clicked
|
||||
private fun onPartySlotClick(slotId: Int, button: Int, clickType: ClickType, player: Player) {
|
||||
val slotItem = getSlot(slotId).item
|
||||
if (clickType == ClickType.CLONE && player.hasInfiniteMaterials() && carried.isEmpty && !slotItem.isEmpty) {
|
||||
carried = slotItem.copyWithCount(slotItem.maxStackSize)
|
||||
} else if (clickType != ClickType.PICKUP) return
|
||||
|
||||
if (serverParty == null) return // Client does nothing
|
||||
|
||||
if (!carried.isEmpty && (isBlacklisted(carried) || !isWhitelisted(carried))) return //Blacklisted and Whitelisted checks
|
||||
|
||||
val index = slotId - PARTY_SLOTS.first
|
||||
val pokemon = serverParty?.get(index) ?: return
|
||||
|
||||
val heldItem = pokemon.heldItem()
|
||||
|
||||
if (carried.isEmpty || carried.count <= 1) { // Can Swap/Pickup
|
||||
val returned = pokemon.swapHeldItem(carried, aiCanDrop = false)
|
||||
carried = returned
|
||||
broadcastChanges()
|
||||
} else if (heldItem.isEmpty) { // Can Placedown
|
||||
pokemon.swapHeldItem(carried, aiCanDrop = false)
|
||||
broadcastChanges()
|
||||
}
|
||||
}
|
||||
|
||||
//Handled only by server
|
||||
fun useHeldItemOnPokemon(partySlot: Int) {
|
||||
if (carried.isEmpty) return
|
||||
|
||||
val pokemon = serverParty?.get(partySlot) ?: return
|
||||
val item = carried.item as? PokemonSelectingItem ?: return
|
||||
val player = playerInventory.player as? ServerPlayer ?: return
|
||||
|
||||
if (player.isInBattle()) return
|
||||
|
||||
val interaction = item.applyToPokemon(player, carried, pokemon)
|
||||
if (interaction?.result == InteractionResult.SUCCESS) {
|
||||
CobblemonCriteria.POKEMON_INTERACT.trigger(player, PokemonInteractContext(pokemon.species.resourceIdentifier, BuiltInRegistries.ITEM.getKey(carried.item)))
|
||||
broadcastChanges()
|
||||
}
|
||||
}
|
||||
|
||||
private fun isBlacklisted(stack: ItemStack): Boolean =
|
||||
BuiltInRegistries.ITEM.getTagOrEmpty(CobblemonItemTags.BLACKLISTED_ITEMS_TO_HOLD).any()
|
||||
&& stack.`is`(CobblemonItemTags.BLACKLISTED_ITEMS_TO_HOLD)
|
||||
|
||||
private fun isWhitelisted(stack: ItemStack): Boolean =
|
||||
BuiltInRegistries.ITEM.getTagOrEmpty(CobblemonItemTags.WHITELISTED_ITEMS_TO_HOLD).none()
|
||||
|| stack.`is`(CobblemonItemTags.WHITELISTED_ITEMS_TO_HOLD)
|
||||
|
||||
override fun quickMoveStack(player: Player, index: Int): ItemStack { // This will only be called by base inventory
|
||||
if (index < 0 || index >= slots.size) return ItemStack.EMPTY
|
||||
val slot = slots[index]
|
||||
val itemStack = slot.item
|
||||
|
||||
val (categoryId, allowedTransfer) = calculateInsertCount(itemStack)
|
||||
if (allowedTransfer <= 0) return ItemStack.EMPTY
|
||||
|
||||
val transferCount = min(itemStack.count, allowedTransfer)
|
||||
|
||||
if (slot.hasItem()) {
|
||||
bagContainer.items.forEach { slotStack ->
|
||||
if (ItemStack.isSameItemSameComponents(slotStack, itemStack)) {
|
||||
slotStack.grow(transferCount)
|
||||
itemStack.shrink(transferCount)
|
||||
categoryItemCounts[categoryId] += transferCount
|
||||
playSound(CobblemonSounds.ITEM_BAG_ITEM_IN)
|
||||
setupSlotsBasedOnContent()
|
||||
return ItemStack.EMPTY
|
||||
}
|
||||
}
|
||||
|
||||
bagContainer.items.add(itemStack.split(transferCount))
|
||||
categoryItemCounts[categoryId] += transferCount
|
||||
playSound(CobblemonSounds.ITEM_BAG_ITEM_IN)
|
||||
setupSlotsBasedOnContent()
|
||||
}
|
||||
return ItemStack.EMPTY
|
||||
}
|
||||
|
||||
fun quickMoveStackFromBag(player: Player, slot: CobblemonBagSlot) { //Called by bag items
|
||||
val transferStack = slot.item
|
||||
val startingCount = transferStack.count
|
||||
|
||||
if (moveItemStackTo(transferStack, INVENTORY_SLOTS.first, HOTBAR_SLOTS.last + 1, false)) {
|
||||
val itemsMoved = startingCount - transferStack.count
|
||||
getAndReduceCategoryCount(slot.remove(itemsMoved))
|
||||
playSound(CobblemonSounds.ITEM_BAG_ITEM_OUT)
|
||||
setupSlotsBasedOnContent()
|
||||
}
|
||||
}
|
||||
|
||||
fun calculateInsertCount(stack: ItemStack): Pair<Int, Int> {
|
||||
if (stack.isEmpty) return -1 to 0
|
||||
|
||||
BagCategories.getOrderedCategoriesList().forEachIndexed { index, category ->
|
||||
if (category.itemIsValid(stack)) {
|
||||
val maxAllowed = max(category.maxCount - categoryItemCounts[index], 0)
|
||||
return index to min(stack.count, maxAllowed)
|
||||
}
|
||||
}
|
||||
return -1 to 0
|
||||
}
|
||||
|
||||
fun getAndReduceCategoryCount(stack: ItemStack) {
|
||||
if (stack.isEmpty) return
|
||||
|
||||
BagCategories.getOrderedCategoriesList().forEachIndexed { index, category ->
|
||||
if (category.itemIsValid(stack)) {
|
||||
categoryItemCounts[index] -= stack.count
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun canTakeItemForPickAll(stack: ItemStack, slot: Slot): Boolean {
|
||||
return slot.index !in BAG_SLOTS
|
||||
}
|
||||
|
||||
fun playSound(soundEvent: SoundEvent) {
|
||||
Minecraft.getInstance().soundManager.play(SimpleSoundInstance.forUI(soundEvent, 1.0F))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.item.bag
|
||||
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import net.minecraft.world.SimpleContainer
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.inventory.Slot
|
||||
import net.minecraft.world.item.ItemStack
|
||||
|
||||
class CobblemonBagPartySlot(
|
||||
container: SimpleContainer,
|
||||
index: Int,
|
||||
val activeGetter: () -> Boolean,
|
||||
val itemGetter: () -> ItemStack,
|
||||
x: Int,
|
||||
y: Int
|
||||
): Slot(container, index, x, y) {
|
||||
override fun getMaxStackSize(): Int = 1
|
||||
|
||||
override fun mayPlace(stack: ItemStack): Boolean = false
|
||||
override fun mayPickup(player: Player): Boolean = false
|
||||
|
||||
override fun getItem(): ItemStack {
|
||||
return itemGetter.invoke()
|
||||
}
|
||||
|
||||
override fun isActive(): Boolean {
|
||||
return activeGetter.invoke()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.item.bag
|
||||
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.inventory.Slot
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import java.util.Optional
|
||||
import kotlin.math.min
|
||||
|
||||
class CobblemonBagSlot(
|
||||
container: CobblemonBagContainer,
|
||||
var simulatedSlot: Int, //Cant override base slot variable so it is forever -1
|
||||
x: Int,
|
||||
y: Int
|
||||
): Slot(container, 0, x, y) {
|
||||
var slotOverflowValue = 0
|
||||
|
||||
override fun set(stack: ItemStack) {}
|
||||
|
||||
override fun getItem(): ItemStack {
|
||||
if (simulatedSlot == -1) return ItemStack.EMPTY
|
||||
val itemStack = container.getItem(simulatedSlot)
|
||||
val count = min(itemStack.count - itemStack.maxStackSize * slotOverflowValue, itemStack.maxStackSize)
|
||||
return itemStack.copyWithCount(count)
|
||||
}
|
||||
|
||||
override fun remove(amount: Int): ItemStack {
|
||||
if (simulatedSlot == -1) return ItemStack.EMPTY
|
||||
return container.removeItem(simulatedSlot, amount)
|
||||
}
|
||||
|
||||
override fun mayPlace(stack: ItemStack): Boolean = false
|
||||
override fun mayPickup(player: Player): Boolean = false
|
||||
}
|
||||
@@ -945,6 +945,8 @@ object CobblemonItemGroups {
|
||||
CobblemonItems.pokeBalls.forEach(entries::accept)
|
||||
CobblemonItems.pokeRods.forEach(entries::accept)
|
||||
CobblemonItems.pokedexes.forEach(entries::accept)
|
||||
entries.accept(CobblemonItems.TRAINER_PACK)
|
||||
entries.accept(CobblemonItems.TRAINER_BAG)
|
||||
}
|
||||
|
||||
private fun blocksInjections(injector: Injector) {
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.item.interactive
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonItemComponents
|
||||
import com.cobblemon.mod.common.item.components.FoodComponent
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.sounds.SoundEvent
|
||||
import net.minecraft.sounds.SoundEvents
|
||||
@@ -23,10 +24,15 @@ import net.minecraft.world.level.Level
|
||||
class PonigiriItem : Item(
|
||||
Properties().stacksTo(64)
|
||||
.food(FoodProperties.Builder()
|
||||
.nutrition(2)
|
||||
.saturationModifier(0.55f)
|
||||
.nutrition(NUTRITION)
|
||||
.saturationModifier(SATURATION_MODIFIER)
|
||||
.build())
|
||||
) {
|
||||
companion object {
|
||||
const val NUTRITION = 2
|
||||
const val SATURATION_MODIFIER = 0.55f
|
||||
}
|
||||
|
||||
override fun getName(stack: ItemStack): Component {
|
||||
|
||||
val ingredients = stack.get(CobblemonItemComponents.INGREDIENT)
|
||||
@@ -59,4 +65,9 @@ class PonigiriItem : Item(
|
||||
override fun getEatingSound(): SoundEvent {
|
||||
return SoundEvents.GENERIC_EAT
|
||||
}
|
||||
}
|
||||
|
||||
fun getFoodValues(stack: ItemStack): Pair<Int, Float> {
|
||||
val (hunger, saturation) = stack.getOrDefault(CobblemonItemComponents.FOOD, FoodComponent(NUTRITION, SATURATION_MODIFIER))
|
||||
return hunger to saturation
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.net.messages.client.bag
|
||||
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
|
||||
class UpdateBagMenuDataPacket(val categoryId: Int, val scroll: Int): NetworkPacket<UpdateBagMenuDataPacket> {
|
||||
companion object {
|
||||
val ID = cobblemonResource("update_bag_menu_data")
|
||||
fun decode(buffer: RegistryFriendlyByteBuf): UpdateBagMenuDataPacket {
|
||||
return UpdateBagMenuDataPacket(buffer.readInt(), buffer.readInt())
|
||||
}
|
||||
}
|
||||
|
||||
override val id = ID
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeInt(categoryId)
|
||||
buffer.writeInt(scroll)
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.net.messages.client.bag
|
||||
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
|
||||
class UseItemOnPokemonFromBagPacket(val partySlot: Int): NetworkPacket<UseItemOnPokemonFromBagPacket> {
|
||||
companion object {
|
||||
val ID = cobblemonResource("use_item_on_pokemon_from_bag")
|
||||
fun decode(buffer: RegistryFriendlyByteBuf): UseItemOnPokemonFromBagPacket {
|
||||
return UseItemOnPokemonFromBagPacket(buffer.readInt())
|
||||
}
|
||||
}
|
||||
override val id = ID
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeInt(partySlot)
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.net.messages.client.data
|
||||
|
||||
import com.cobblemon.mod.common.api.bag.BagCategories
|
||||
import com.cobblemon.mod.common.api.bag.BagCategory
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
|
||||
class BagCategoriesSyncPacket(categories: List<BagCategory>): DataRegistrySyncPacket<BagCategory, BagCategoriesSyncPacket>(categories) {
|
||||
companion object {
|
||||
val ID = cobblemonResource("bag_categories")
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) = BagCategoriesSyncPacket(emptyList()).apply { decodeBuffer(buffer) }
|
||||
}
|
||||
|
||||
override val id = ID
|
||||
override fun encodeEntry(buffer: RegistryFriendlyByteBuf, entry: BagCategory) {
|
||||
entry.encode(buffer)
|
||||
}
|
||||
|
||||
override fun decodeEntry(buffer: RegistryFriendlyByteBuf): BagCategory = BagCategory.decode(buffer)
|
||||
|
||||
override fun synchronizeDecoded(entries: Collection<BagCategory>) {
|
||||
BagCategories.reload(entries.associateBy { it.identifier })
|
||||
}
|
||||
}
|
||||
+7
-4
@@ -23,16 +23,19 @@ import java.util.UUID
|
||||
* @author Hiroku
|
||||
* @since March 5th, 2023
|
||||
*/
|
||||
class TradeCompletedPacket(val pokemonId1: UUID, val pokemonId2: UUID) : NetworkPacket<TradeCompletedPacket> {
|
||||
class TradeCompletedPacket(val pokemonIds1: List<UUID>, val pokemonIds2: List<UUID>) : NetworkPacket<TradeCompletedPacket> {
|
||||
companion object {
|
||||
val ID = cobblemonResource("trade_completed")
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) = TradeCompletedPacket(buffer.readUUID(), buffer.readUUID())
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) = TradeCompletedPacket(
|
||||
buffer.readList { it.readUUID() },
|
||||
buffer.readList { it.readUUID() }
|
||||
)
|
||||
}
|
||||
|
||||
override val id = ID
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeUUID(pokemonId1)
|
||||
buffer.writeUUID(pokemonId2)
|
||||
buffer.writeCollection(pokemonIds1) { buf, id -> buf.writeUUID(id) }
|
||||
buffer.writeCollection(pokemonIds2) { buf, id -> buf.writeUUID(id) }
|
||||
}
|
||||
}
|
||||
+6
-7
@@ -12,10 +12,6 @@ import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.api.net.UnsplittablePacket
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.readNullable
|
||||
import com.cobblemon.mod.common.util.readUUID
|
||||
import com.cobblemon.mod.common.util.writeNullable
|
||||
import com.cobblemon.mod.common.util.writeUUID
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import java.util.UUID
|
||||
|
||||
@@ -27,15 +23,18 @@ import java.util.UUID
|
||||
* @author Hiroku
|
||||
* @since March 5th, 2023
|
||||
*/
|
||||
class TradeUpdatedPacket(val playerId: UUID, val pokemon: Pokemon?) : NetworkPacket<TradeUpdatedPacket>, UnsplittablePacket {
|
||||
class TradeUpdatedPacket(val playerId: UUID, val pokemons: List<Pokemon>) : NetworkPacket<TradeUpdatedPacket>, UnsplittablePacket {
|
||||
companion object {
|
||||
val ID = cobblemonResource("trade_updated")
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) = TradeUpdatedPacket(buffer.readUUID(), buffer.readNullable { Pokemon.S2C_CODEC.decode(buffer) })
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) = TradeUpdatedPacket(
|
||||
buffer.readUUID(),
|
||||
buffer.readList { Pokemon.S2C_CODEC.decode(it as RegistryFriendlyByteBuf) }
|
||||
)
|
||||
}
|
||||
|
||||
override val id = ID
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeUUID(playerId)
|
||||
buffer.writeNullable(pokemon) { _, pokemon -> Pokemon.S2C_CODEC.encode(buffer, pokemon) }
|
||||
buffer.writeCollection(pokemons) { buf, pokemon -> Pokemon.S2C_CODEC.encode(buf as RegistryFriendlyByteBuf, pokemon) }
|
||||
}
|
||||
}
|
||||
+9
-5
@@ -11,26 +11,30 @@ package com.cobblemon.mod.common.net.messages.server.trade
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.api.storage.party.PartyPosition
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.readList
|
||||
import com.cobblemon.mod.common.util.readNullable
|
||||
import com.cobblemon.mod.common.util.readPartyPosition
|
||||
import com.cobblemon.mod.common.util.readUUID
|
||||
import com.cobblemon.mod.common.util.writeCollection
|
||||
import com.cobblemon.mod.common.util.writeNullable
|
||||
import com.cobblemon.mod.common.util.writePartyPosition
|
||||
import com.cobblemon.mod.common.util.writeUUID
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import java.util.UUID
|
||||
|
||||
class UpdateTradeOfferPacket(val newOffer: Pair<UUID, PartyPosition>?): NetworkPacket<UpdateTradeOfferPacket> {
|
||||
class UpdateTradeOfferPacket(val newOffers: List<Pair<UUID, PartyPosition>>): NetworkPacket<UpdateTradeOfferPacket> {
|
||||
companion object {
|
||||
val ID = cobblemonResource("update_trade_offer")
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) = UpdateTradeOfferPacket(buffer.readNullable { buffer.readUUID() to buffer.readPartyPosition() })
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) = UpdateTradeOfferPacket(
|
||||
buffer.readList { it.readUUID() to it.readPartyPosition() }
|
||||
)
|
||||
}
|
||||
|
||||
override val id = ID
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeNullable(newOffer) { buffer, (pokemonId, partyPosition) ->
|
||||
buffer.writeUUID(pokemonId)
|
||||
buffer.writePartyPosition(partyPosition)
|
||||
buffer.writeCollection(newOffers) { buf, (pokemonId, partyPosition) ->
|
||||
buf.writeUUID(pokemonId)
|
||||
buf.writePartyPosition(partyPosition)
|
||||
}
|
||||
}
|
||||
}
|
||||
+24
@@ -8,9 +8,12 @@
|
||||
|
||||
package com.cobblemon.mod.common.net.serverhandling.battle
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.net.ServerNetworkPacketHandler
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.battles.BattleRegistry
|
||||
import com.cobblemon.mod.common.battles.HealItemActionResponse
|
||||
import com.cobblemon.mod.common.battles.MoveActionResponse
|
||||
import com.cobblemon.mod.common.exception.IllegalActionChoiceException
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.BattleMakeChoicePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.BattleQueueRequestPacket
|
||||
@@ -25,6 +28,27 @@ object BattleSelectActionsHandler : ServerNetworkPacketHandler<BattleSelectActio
|
||||
if (!actor.mustChoose) {
|
||||
return
|
||||
}
|
||||
|
||||
// Battle command injection attempt detection
|
||||
packet.showdownActionResponses.asSequence()
|
||||
.flatMap {
|
||||
when (it) {
|
||||
is MoveActionResponse -> sequenceOf(it.moveName, it.targetPnx, it.gimmickID)
|
||||
is HealItemActionResponse -> sequenceOf(it.item)
|
||||
else -> emptySequence()
|
||||
}
|
||||
}
|
||||
.filterNotNull()
|
||||
.firstOrNull { field -> field.any(Char::isISOControl) }
|
||||
?.let {
|
||||
// Escapes control chars as \uXXXX to prevent forging logs.
|
||||
val printable = it.replace(Regex("\\p{Cc}")) { "\\u%04x".format(it.value[0].code) }
|
||||
Cobblemon.LOGGER.warn("Blocked battle command injection from ${player.name.string}: $printable")
|
||||
actor.sendUpdate(BattleQueueRequestPacket(actor.request!!))
|
||||
actor.sendUpdate(BattleMakeChoicePacket())
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
actor.setActionResponses(packet.showdownActionResponses)
|
||||
} catch (e: IllegalActionChoiceException) {
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ object ChangeTradeAcceptanceHandler : ServerNetworkPacketHandler<ChangeTradeAcce
|
||||
override fun handle(packet: ChangeTradeAcceptancePacket, server: MinecraftServer, player: ServerPlayer) {
|
||||
val trade = TradeManager.getActiveTrade(player.uuid) ?: return player.sendPacket(TradeCancelledPacket())
|
||||
val tradeParticipant = trade.getTradeParticipant(player.uuid)
|
||||
if (trade.getOpposingOffer(tradeParticipant).pokemon?.uuid == packet.pokemonOfferId) {
|
||||
if (trade.getOpposingOffer(tradeParticipant).pokemon.any { it.uuid == packet.pokemonOfferId }) {
|
||||
trade.updateAcceptance(tradeParticipant, packet.newAcceptance)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ object PerformTradeHandler : ServerNetworkPacketHandler<PerformTradePacket> {
|
||||
override fun handle(packet: PerformTradePacket, server: MinecraftServer, player: ServerPlayer) {
|
||||
val trade = TradeManager.getActiveTrade(player.uuid) ?: return player.sendPacket(TradeCancelledPacket())
|
||||
val tradeParticipant = trade.getTradeParticipant(player.uuid)
|
||||
if (trade.getOpposingOffer(tradeParticipant).pokemon?.uuid == packet.pokemonOfferId) {
|
||||
if (trade.getOpposingOffer(tradeParticipant).pokemon.any { it.uuid == packet.pokemonOfferId }) {
|
||||
trade.performTrade(tradeParticipant)
|
||||
}
|
||||
}
|
||||
|
||||
+9
-12
@@ -12,6 +12,7 @@ import com.cobblemon.mod.common.CobblemonNetwork.sendPacket
|
||||
import com.cobblemon.mod.common.api.net.ServerNetworkPacketHandler
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.CancelTradePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.UpdateTradeOfferPacket
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.trade.TradeManager
|
||||
import com.cobblemon.mod.common.util.party
|
||||
import net.minecraft.server.MinecraftServer
|
||||
@@ -21,20 +22,16 @@ object UpdateTradeOfferHandler : ServerNetworkPacketHandler<UpdateTradeOfferPack
|
||||
override fun handle(packet: UpdateTradeOfferPacket, server: MinecraftServer, player: ServerPlayer) {
|
||||
val trade = TradeManager.getActiveTrade(player.uuid) ?: return player.sendPacket(CancelTradePacket())
|
||||
val tradeParticipant = trade.getTradeParticipant(player.uuid)
|
||||
val newOffer = packet.newOffer
|
||||
if (newOffer == null) {
|
||||
trade.updateOffer(tradeParticipant, null)
|
||||
} else {
|
||||
val (pokemonId, partyPosition) = newOffer
|
||||
val party = player.party()
|
||||
val newOffers = packet.newOffers
|
||||
|
||||
val validPokemons = mutableListOf<Pokemon>()
|
||||
val party = player.party()
|
||||
for ((pokemonId, partyPosition) in newOffers) {
|
||||
val pokemon = party[partyPosition]
|
||||
if (pokemon == null || pokemon.uuid != pokemonId) {
|
||||
return
|
||||
} else if (!pokemon.tradeable) {
|
||||
return
|
||||
} else {
|
||||
trade.updateOffer(tradeParticipant, pokemon)
|
||||
if (pokemon != null && pokemon.uuid == pokemonId && pokemon.tradeable) {
|
||||
validPokemons.add(pokemon)
|
||||
}
|
||||
}
|
||||
trade.updateOffer(tradeParticipant, validPokemons)
|
||||
}
|
||||
}
|
||||
@@ -173,6 +173,7 @@ class Species : ShowdownIdentifiable {
|
||||
.addStandardFunctions()
|
||||
.addSpeciesFunctions(this)
|
||||
|
||||
var silenceStepSounds = false
|
||||
|
||||
fun initialize() {
|
||||
Cobblemon.statProvider.provide(this)
|
||||
@@ -256,6 +257,7 @@ class Species : ShowdownIdentifiable {
|
||||
}
|
||||
|
||||
this.riding.encode(buffer)
|
||||
buffer.writeBoolean(this.silenceStepSounds)
|
||||
}
|
||||
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
@@ -299,6 +301,7 @@ class Species : ShowdownIdentifiable {
|
||||
}
|
||||
}
|
||||
this.riding = RidingProperties.decode(buffer)
|
||||
this.silenceStepSounds = buffer.readBoolean()
|
||||
this.initialize()
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ class ActiveTrade(val player1: TradeParticipant, val player2: TradeParticipant)
|
||||
fun getOffer(tradeParticipant: TradeParticipant) = if (tradeParticipant == player1) player1Offer else player2Offer
|
||||
fun getOpposingOffer(tradeParticipant: TradeParticipant) = if (tradeParticipant == player1) player2Offer else player1Offer
|
||||
|
||||
fun updateOffer(tradeParticipant: TradeParticipant, pokemon: Pokemon?) {
|
||||
fun updateOffer(tradeParticipant: TradeParticipant, pokemon: List<Pokemon>) {
|
||||
getOffer(tradeParticipant).updateOffer(pokemon)
|
||||
getOffer(getOppositePlayer(tradeParticipant)).accepted = false
|
||||
player1.updateOffer(this, tradeParticipant, pokemon)
|
||||
@@ -30,8 +30,9 @@ class ActiveTrade(val player1: TradeParticipant, val player2: TradeParticipant)
|
||||
val offer = getOpposingOffer(tradeParticipant)
|
||||
if (offer.accepted != acceptance) {
|
||||
offer.accepted = acceptance
|
||||
getOppositePlayer(tradeParticipant).changeTradeAcceptance(this, offer.pokemon!!.uuid, acceptance)
|
||||
tradeParticipant.changeTradeAcceptance(this, offer.pokemon!!.uuid, acceptance)
|
||||
val firstId = offer.pokemon.firstOrNull()?.uuid ?: java.util.UUID.randomUUID()
|
||||
getOppositePlayer(tradeParticipant).changeTradeAcceptance(this, firstId, acceptance)
|
||||
tradeParticipant.changeTradeAcceptance(this, firstId, acceptance)
|
||||
}
|
||||
|
||||
if (offer.accepted && getOffer(tradeParticipant).accepted) {
|
||||
@@ -51,8 +52,8 @@ class ActiveTrade(val player1: TradeParticipant, val player2: TradeParticipant)
|
||||
activeTrade = this,
|
||||
player1 = player1,
|
||||
player2 = player2,
|
||||
pokemon1 = player1Offer.pokemon!!,
|
||||
pokemon2 = player2Offer.pokemon!!
|
||||
pokemon1 = player1Offer.pokemon,
|
||||
pokemon2 = player2Offer.pokemon
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -64,12 +65,14 @@ class ActiveTrade(val player1: TradeParticipant, val player2: TradeParticipant)
|
||||
}
|
||||
|
||||
fun completeTrade() {
|
||||
player1.completeTrade(this, player1Offer.pokemon!!.uuid, player2Offer.pokemon!!.uuid)
|
||||
player2.completeTrade(this, player2Offer.pokemon!!.uuid, player1Offer.pokemon!!.uuid)
|
||||
val uuids1 = player1Offer.pokemon.map { it.uuid }
|
||||
val uuids2 = player2Offer.pokemon.map { it.uuid }
|
||||
player1.completeTrade(this, uuids1, uuids2)
|
||||
player2.completeTrade(this, uuids2, uuids1)
|
||||
|
||||
player1Offer.pokemon = null
|
||||
player1Offer.pokemon = emptyList()
|
||||
player1Offer.accepted = false
|
||||
player2Offer.pokemon = null
|
||||
player2Offer.pokemon = emptyList()
|
||||
player2Offer.accepted = false
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ import com.cobblemon.mod.common.api.events.CobblemonEvents
|
||||
import com.cobblemon.mod.common.api.events.pokemon.TradeEvent
|
||||
import com.cobblemon.mod.common.api.interaction.ServerPlayerActionRequest
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.api.storage.party.PartyStore
|
||||
import com.cobblemon.mod.common.api.text.aqua
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeOfferExpiredPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeOfferNotificationPacket
|
||||
@@ -101,71 +102,98 @@ object TradeManager : RequestManager<TradeManager.TradeRequest>() {
|
||||
fun performTrade(
|
||||
activeTrade: ActiveTrade,
|
||||
player1: TradeParticipant,
|
||||
pokemon1: Pokemon,
|
||||
pokemon1: List<Pokemon>,
|
||||
player2: TradeParticipant,
|
||||
pokemon2: Pokemon
|
||||
pokemon2: List<Pokemon>
|
||||
) {
|
||||
val party1 = player1.party
|
||||
val party2 = player2.party
|
||||
|
||||
if (pokemon1 !in party1 || pokemon2 !in party2) {
|
||||
if (pokemon1.any { it !in party1 } || pokemon2.any { it !in party2 }) {
|
||||
Cobblemon.LOGGER.warn("Attempted to perform a trade with Pokémon that aren't in the party anymore. Could be attempted duping between ${player1.name} and ${player2.name}")
|
||||
activeTrade.cancelTrade()
|
||||
return
|
||||
}
|
||||
|
||||
CobblemonEvents.TRADE_EVENT_PRE.postThen(TradeEvent.Pre(player1, pokemon2, player2, pokemon1)) {
|
||||
val party1 = player1.party
|
||||
val party2 = player2.party
|
||||
if (pokemon1.isEmpty() || pokemon2.isEmpty()) {
|
||||
Cobblemon.LOGGER.warn("Attempted to perform a trade where one side offered no Pokémon between ${player1.name} and ${player2.name}. This should never happen.")
|
||||
activeTrade.cancelTrade()
|
||||
return
|
||||
}
|
||||
|
||||
val player1Removed = party1.remove(pokemon1)
|
||||
val player2Removed = party2.remove(pokemon2)
|
||||
CobblemonEvents.TRADE_EVENT_PRE.postThen(
|
||||
TradeEvent.Pre(player1, pokemon2, player2, pokemon1)
|
||||
) {
|
||||
val player1Removed = pokemon1.filter { party1.remove(it) }
|
||||
val player2Removed = pokemon2.filter { party2.remove(it) }
|
||||
|
||||
if (!player1Removed || !player2Removed) {
|
||||
if (!player1Removed) {
|
||||
Cobblemon.LOGGER.warn("Failed to remove traded Pokémon ${pokemon1.species.resourceIdentifier} from ${player1.name.string}(${player1.uuid}). Aborting trade with ${player2.name.string}(${player2.uuid}), potential exploit abused.")
|
||||
if (player1Removed.size != pokemon1.size || player2Removed.size != pokemon2.size) {
|
||||
(pokemon1 - player1Removed.toSet()).forEach {
|
||||
Cobblemon.LOGGER.warn("Failed to remove traded Pokémon ${it.species.resourceIdentifier} from ${player1.name.string}(${player1.uuid}). Aborting trade with ${player2.name.string}(${player2.uuid}), potential exploit abused.")
|
||||
}
|
||||
|
||||
if (!player2Removed) {
|
||||
Cobblemon.LOGGER.warn("Failed to remove traded Pokémon ${pokemon2.species.resourceIdentifier} from ${player2.name.string}(${player2.uuid}). Aborting trade with ${player1.name.string}(${player1.uuid}), potential exploit abused.")
|
||||
(pokemon2 - player2Removed.toSet()).forEach {
|
||||
Cobblemon.LOGGER.warn("Failed to remove traded Pokémon ${it.species.resourceIdentifier} from ${player2.name.string}(${player2.uuid}). Aborting trade with ${player1.name.string}(${player1.uuid}), potential exploit abused.")
|
||||
}
|
||||
|
||||
// Revert any changes if one of the removals failed
|
||||
if (player1Removed) party1.add(pokemon1)
|
||||
if (player2Removed) party2.add(pokemon2)
|
||||
player1Removed.forEach { party1.add(it) }
|
||||
player2Removed.forEach { party2.add(it) }
|
||||
return@postThen
|
||||
}
|
||||
|
||||
// If player1 is the OT, keep track of the friendship
|
||||
pokemon1.cacheFriendship(player1.uuid)
|
||||
pokemon1.forEach { it.cacheFriendship(player1.uuid) }
|
||||
// If player2 is the OT, keep track of the friendship
|
||||
pokemon2.cacheFriendship(player2.uuid)
|
||||
pokemon2.forEach { it.cacheFriendship(player2.uuid) }
|
||||
|
||||
// If pokemon2 was originally player1's, set the friendship back to what it was at point of trading
|
||||
if ( !pokemon2.restoreFriendship(player1.uuid) ) {
|
||||
// Otherwise, reset the friendship
|
||||
pokemon2.setFriendship(pokemon2.form.baseFriendship)
|
||||
// If a Pokémon received by player1 was originally theirs, set the friendship back to what it was at point of trading
|
||||
pokemon2.forEach {
|
||||
if (!it.restoreFriendship(player1.uuid)) {
|
||||
// Otherwise, reset the friendship
|
||||
it.setFriendship(it.form.baseFriendship)
|
||||
}
|
||||
}
|
||||
// If pokemon1 was originally player2's, set the friendship back to what it was at point of trading
|
||||
if ( !pokemon1.restoreFriendship(player2.uuid) ) {
|
||||
// Otherwise, reset the friendship
|
||||
pokemon1.setFriendship(pokemon1.form.baseFriendship)
|
||||
// If a Pokémon received by player2 was originally theirs, set the friendship back to what it was at point of trading
|
||||
pokemon1.forEach {
|
||||
if (!it.restoreFriendship(player2.uuid)) {
|
||||
// Otherwise, reset the friendship
|
||||
it.setFriendship(it.form.baseFriendship)
|
||||
}
|
||||
}
|
||||
|
||||
party2.add(pokemon1)
|
||||
party1.add(pokemon2)
|
||||
pokemon1.forEach { party2.add(it) }
|
||||
pokemon2.forEach { party1.add(it) }
|
||||
|
||||
pokemon1.lockedEvolutions.filterIsInstance<TradeEvolution>().firstOrNull {
|
||||
it.attemptEvolution(pokemon1, pokemon2)
|
||||
}
|
||||
// Each traded Pokémon may evolve if any of the Pokémon it was traded for satisfies its context.
|
||||
// Evolutions are resolved before any are applied so one evolving can't invalidate another's context.
|
||||
(pokemon1.map { it to pokemon2 } + pokemon2.map { it to pokemon1 })
|
||||
.mapNotNull { (pokemon, tradedFor) ->
|
||||
pokemon.lockedEvolutions.filterIsInstance<TradeEvolution>()
|
||||
.firstOrNull { evolution -> tradedFor.any { evolution.testContext(pokemon, it) } && evolution.test(pokemon) }
|
||||
?.let { pokemon to it }
|
||||
}
|
||||
.forEach { (pokemon, evolution) -> evolution.evolve(pokemon) }
|
||||
|
||||
pokemon2.lockedEvolutions.filterIsInstance<TradeEvolution>().firstOrNull {
|
||||
it.attemptEvolution(pokemon2, pokemon1)
|
||||
val compactParty = { party: PartyStore ->
|
||||
var writeIdx = 0
|
||||
for (readIdx in 0 until party.size()) {
|
||||
if (party.get(readIdx) != null) {
|
||||
if (readIdx != writeIdx) {
|
||||
party.swap(readIdx, writeIdx)
|
||||
}
|
||||
writeIdx++
|
||||
}
|
||||
}
|
||||
}
|
||||
compactParty(party1)
|
||||
compactParty(party2)
|
||||
|
||||
activeTrade.completeTrade()
|
||||
|
||||
CobblemonEvents.TRADE_EVENT_POST.post(TradeEvent.Post(player1, pokemon2, player2, pokemon1))
|
||||
CobblemonEvents.TRADE_EVENT_POST.post(
|
||||
TradeEvent.Post(player1, pokemon2, player2, pokemon1)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,10 +11,10 @@ package com.cobblemon.mod.common.trade
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
|
||||
class TradeOffer {
|
||||
var pokemon: Pokemon? = null
|
||||
var pokemon: List<Pokemon> = emptyList()
|
||||
var accepted = false
|
||||
|
||||
fun updateOffer(pokemon: Pokemon?) {
|
||||
fun updateOffer(pokemon: List<Pokemon>) {
|
||||
this.pokemon = pokemon
|
||||
accepted = false
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ interface TradeParticipant {
|
||||
*
|
||||
* If it's null, it means they're no longer offering a Pokémon (so they're redeciding).
|
||||
*/
|
||||
fun updateOffer(trade: ActiveTrade, tradeParticipant: TradeParticipant, pokemon: Pokemon?)
|
||||
fun updateOffer(trade: ActiveTrade, tradeParticipant: TradeParticipant, pokemon: List<Pokemon>)
|
||||
|
||||
/**
|
||||
* Notifies the participant that the acceptance state for trading with the opponent [Pokemon] with UUID [pokemonId]
|
||||
@@ -59,7 +59,7 @@ interface TradeParticipant {
|
||||
fun cancelTrade(trade: ActiveTrade)
|
||||
|
||||
/** Notifies the participant that the trade has been completed. The actual Pokémon have already been exchanged. */
|
||||
fun completeTrade(trade: ActiveTrade, pokemonId1: UUID, pokemonId2: UUID)
|
||||
fun completeTrade(trade: ActiveTrade, pokemonIds1: List<UUID>, pokemonIds2: List<UUID>)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -73,7 +73,7 @@ class PlayerTradeParticipant(val player: ServerPlayer): TradeParticipant {
|
||||
override val uuid = player.uuid
|
||||
override val party = player.party()
|
||||
|
||||
override fun updateOffer(trade: ActiveTrade, tradeParticipant: TradeParticipant, pokemon: Pokemon?) {
|
||||
override fun updateOffer(trade: ActiveTrade, tradeParticipant: TradeParticipant, pokemon: List<Pokemon>) {
|
||||
player.sendPacket(TradeUpdatedPacket(tradeParticipant.uuid, pokemon))
|
||||
}
|
||||
|
||||
@@ -89,8 +89,8 @@ class PlayerTradeParticipant(val player: ServerPlayer): TradeParticipant {
|
||||
player.sendPacket(TradeCancelledPacket())
|
||||
}
|
||||
|
||||
override fun completeTrade(trade: ActiveTrade, pokemonId1: UUID, pokemonId2: UUID) {
|
||||
player.sendPacket(TradeCompletedPacket(pokemonId1, pokemonId2))
|
||||
override fun completeTrade(trade: ActiveTrade, pokemonIds1: List<UUID>, pokemonIds2: List<UUID>) {
|
||||
player.sendPacket(TradeCompletedPacket(pokemonIds1, pokemonIds2))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ class DummyTradeParticipant(val pokemonList: MutableList<Pokemon>) : TradePartic
|
||||
// Don't need to do any notifying.
|
||||
}
|
||||
|
||||
override fun completeTrade(trade: ActiveTrade, pokemonId1: UUID, pokemonId2: UUID) {
|
||||
override fun completeTrade(trade: ActiveTrade, pokemonIds1: List<UUID>, pokemonIds2: List<UUID>) {
|
||||
// Don't need to do any notifying.
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ class DummyTradeParticipant(val pokemonList: MutableList<Pokemon>) : TradePartic
|
||||
// React, maybe. Change code and hotswap.
|
||||
}
|
||||
|
||||
override fun updateOffer(trade: ActiveTrade, tradeParticipant: TradeParticipant, pokemon: Pokemon?) {
|
||||
override fun updateOffer(trade: ActiveTrade, tradeParticipant: TradeParticipant, pokemon: List<Pokemon>) {
|
||||
// React, maybe. Change code and hotswap.
|
||||
}
|
||||
}
|
||||
@@ -234,11 +234,11 @@ fun Entity.isDusk(): Boolean {
|
||||
}
|
||||
|
||||
fun Entity.isStandingOn(blocks: Set<String>, depth: Int = 2): Boolean {
|
||||
for (currentDepth in 1..depth) {
|
||||
val bellowBlockPos = blockPosition().below(currentDepth)
|
||||
for (currentDepth in 0..depth) {
|
||||
val bellowBlockPos = blockPosBelowThatAffectsMyMovement.below(currentDepth)
|
||||
val blockState = level().getBlockState(bellowBlockPos)
|
||||
|
||||
if (blockState.isAir || !blockState.isCollisionShapeFullBlock(level(), bellowBlockPos)) continue
|
||||
if (blockState.isAir) continue
|
||||
|
||||
val elementOrTags = ExtraCodecs.TAG_OR_ELEMENT_ID.listOf().decode(JavaOps.INSTANCE, blocks.toList()).result().get().first
|
||||
elementOrTags.forEach {
|
||||
|
||||
@@ -27,5 +27,9 @@ object CobblemonGameRules {
|
||||
@JvmField
|
||||
val HEALERS_HEAL_PC: GameRules.Key<GameRules.BooleanValue> = Cobblemon.implementation.registerGameRule("healersHealPC", GameRules.Category.MISC, BooleanRuleInvoker.`cobblemon$create`(false))
|
||||
@JvmField
|
||||
val HEALER_SET_SPAWN: GameRules.Key<GameRules.BooleanValue> = Cobblemon.implementation.registerGameRule("healersSetSpawn", GameRules.Category.MISC, BooleanRuleInvoker.`cobblemon$create`(false))
|
||||
@JvmField
|
||||
val DO_POKEMON_PREDATION: GameRules.Key<GameRules.BooleanValue> = Cobblemon.implementation.registerGameRule("doPokemonPredation", GameRules.Category.MOBS, BooleanRuleInvoker.`cobblemon$create`(true))
|
||||
@JvmField
|
||||
val BAG_DROP_ITEMS: GameRules.Key<GameRules.BooleanValue> = Cobblemon.implementation.registerGameRule("bagDropItems", GameRules.Category.PLAYER, BooleanRuleInvoker.`cobblemon$create`(false))
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
{
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:watershuriken_actor",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_blend",
|
||||
"texture": "textures/particles/moves/watershuriken"
|
||||
}
|
||||
},
|
||||
"curves": {
|
||||
"variable.rsize": {
|
||||
"type": "linear",
|
||||
"input": "v.particle_age",
|
||||
"horizontal_range": "v.particle_lifetime",
|
||||
"nodes": [0, 1, 1, 1, 1, 1, 1, 1]
|
||||
}
|
||||
},
|
||||
"events": {
|
||||
"trail": {
|
||||
"particle_effect": {
|
||||
"effect": "cobblemon:watershuriken_actortrail",
|
||||
"type": "particle"
|
||||
}
|
||||
},
|
||||
"hit": {
|
||||
"particle_effect": {
|
||||
"effect": "cobblemon:watershuriken_target",
|
||||
"type": "particle"
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_initialization": {
|
||||
"creation_expression": "v.target_deltaz=5;"
|
||||
},
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 1
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 0.25
|
||||
},
|
||||
"minecraft:emitter_shape_disc": {
|
||||
"offset": [0, 0.02, 0.1],
|
||||
"radius": 0.5,
|
||||
"direction": "outwards"
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 0.35
|
||||
},
|
||||
"minecraft:particle_lifetime_events": {
|
||||
"timeline": {
|
||||
"0.00": "trail",
|
||||
"0.06": "trail",
|
||||
"0.12": "trail",
|
||||
"0.18": "trail",
|
||||
"0.24": "trail",
|
||||
"0.30": "trail",
|
||||
"0.34": "hit"
|
||||
}
|
||||
},
|
||||
"minecraft:particle_initial_spin": {
|
||||
"rotation": "math.random_integer(0,3)*90"
|
||||
},
|
||||
"minecraft:particle_motion_parametric": {
|
||||
"relative_position": ["-v.target_deltax*(v.particle_age / v.particle_lifetime)", "(v.target_deltay*(v.particle_age / v.particle_lifetime))", "-v.target_deltaz*(v.particle_age / v.particle_lifetime)"]
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": ["0.4*v.rsize", "0.4*v.rsize"],
|
||||
"facing_camera_mode": "lookat_direction",
|
||||
"direction": {
|
||||
"mode": "custom",
|
||||
"custom_direction": [0, 0, -1]
|
||||
},
|
||||
"uv": {
|
||||
"texture_width": 60,
|
||||
"texture_height": 15,
|
||||
"flipbook": {
|
||||
"base_UV": [0, 0],
|
||||
"size_UV": [15, 15],
|
||||
"step_UV": [15, 0],
|
||||
"frames_per_second": 24,
|
||||
"max_frame": 4,
|
||||
"loop": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
{
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:watershuriken_actoralt",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_blend",
|
||||
"texture": "textures/particles/moves/watershuriken"
|
||||
}
|
||||
},
|
||||
"curves": {
|
||||
"variable.rsize": {
|
||||
"type": "linear",
|
||||
"input": "v.particle_age",
|
||||
"horizontal_range": "v.particle_lifetime",
|
||||
"nodes": [0, 1, 1, 1, 1, 1, 1, 1]
|
||||
}
|
||||
},
|
||||
"events": {
|
||||
"trail": {
|
||||
"particle_effect": {
|
||||
"effect": "cobblemon:watershuriken_actortrail",
|
||||
"type": "particle"
|
||||
}
|
||||
},
|
||||
"hit": {
|
||||
"particle_effect": {
|
||||
"effect": "cobblemon:watershuriken_target",
|
||||
"type": "particle"
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_initialization": {
|
||||
"creation_expression": "v.target_deltaz=5;"
|
||||
},
|
||||
"minecraft:emitter_rate_steady": {
|
||||
"spawn_rate": 7,
|
||||
"max_particles": 3
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 0.4
|
||||
},
|
||||
"minecraft:emitter_shape_disc": {
|
||||
"offset": [0, 0.02, 0.1],
|
||||
"radius": 0.5,
|
||||
"direction": "outwards"
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 0.35
|
||||
},
|
||||
"minecraft:particle_lifetime_events": {
|
||||
"timeline": {
|
||||
"0.00": "trail",
|
||||
"0.06": "trail",
|
||||
"0.12": "trail",
|
||||
"0.18": "trail",
|
||||
"0.24": "trail",
|
||||
"0.30": "trail",
|
||||
"0.34": "hit"
|
||||
}
|
||||
},
|
||||
"minecraft:particle_initial_spin": {
|
||||
"rotation": "math.random_integer(0,3)*90"
|
||||
},
|
||||
"minecraft:particle_motion_parametric": {
|
||||
"relative_position": ["-(v.target_deltax+((v.particle_random_1-0.5)*1.33))*(v.particle_age / v.particle_lifetime)", "(v.target_deltay+((v.particle_random_2-0.5)*1.33))*(v.particle_age / v.particle_lifetime)", "-v.target_deltaz*(v.particle_age / v.particle_lifetime)"]
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": ["0.4*v.rsize", "0.4*v.rsize"],
|
||||
"facing_camera_mode": "lookat_direction",
|
||||
"direction": {
|
||||
"mode": "custom",
|
||||
"custom_direction": [0, 0, -1]
|
||||
},
|
||||
"uv": {
|
||||
"texture_width": 60,
|
||||
"texture_height": 15,
|
||||
"flipbook": {
|
||||
"base_UV": [0, 0],
|
||||
"size_UV": [15, 15],
|
||||
"step_UV": [15, 0],
|
||||
"frames_per_second": 24,
|
||||
"max_frame": 4,
|
||||
"loop": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
{
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:watershuriken_actorhor",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_blend",
|
||||
"texture": "textures/particles/moves/watershuriken"
|
||||
}
|
||||
},
|
||||
"curves": {
|
||||
"variable.rsize": {
|
||||
"type": "linear",
|
||||
"input": "v.particle_age",
|
||||
"horizontal_range": "v.particle_lifetime",
|
||||
"nodes": [0, 1, 1, 1, 1, 1, 1, 1]
|
||||
}
|
||||
},
|
||||
"events": {
|
||||
"trail": {
|
||||
"particle_effect": {
|
||||
"effect": "cobblemon:watershuriken_actortrail",
|
||||
"type": "particle"
|
||||
}
|
||||
},
|
||||
"hit": {
|
||||
"particle_effect": {
|
||||
"effect": "cobblemon:watershuriken_target",
|
||||
"type": "particle"
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_initialization": {
|
||||
"creation_expression": "v.target_deltaz=5;"
|
||||
},
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 1
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 0.25
|
||||
},
|
||||
"minecraft:emitter_shape_disc": {
|
||||
"offset": [0, 0.02, 0.1],
|
||||
"radius": 0.5,
|
||||
"direction": "outwards"
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 0.35
|
||||
},
|
||||
"minecraft:particle_lifetime_events": {
|
||||
"timeline": {
|
||||
"0.00": "trail",
|
||||
"0.06": "trail",
|
||||
"0.12": "trail",
|
||||
"0.18": "trail",
|
||||
"0.24": "trail",
|
||||
"0.30": "trail",
|
||||
"0.34": "hit"
|
||||
}
|
||||
},
|
||||
"minecraft:particle_initial_spin": {
|
||||
"rotation": "math.random_integer(0,3)*90"
|
||||
},
|
||||
"minecraft:particle_motion_parametric": {
|
||||
"relative_position": ["-v.target_deltax*(v.particle_age / v.particle_lifetime)", "(v.target_deltay*(v.particle_age / v.particle_lifetime))", "-v.target_deltaz*(v.particle_age / v.particle_lifetime)"]
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": ["0.4*v.rsize", "0.4*v.rsize"],
|
||||
"facing_camera_mode": "emitter_transform_xz",
|
||||
"uv": {
|
||||
"texture_width": 60,
|
||||
"texture_height": 15,
|
||||
"flipbook": {
|
||||
"base_UV": [0, 0],
|
||||
"size_UV": [15, 15],
|
||||
"step_UV": [15, 0],
|
||||
"frames_per_second": 24,
|
||||
"max_frame": 4,
|
||||
"loop": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
{
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:watershuriken_actortrail",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/generic/impact/impact_water"
|
||||
}
|
||||
},
|
||||
"curves": {
|
||||
"variable.scale": {
|
||||
"type": "linear",
|
||||
"input": "v.particle_age",
|
||||
"horizontal_range": "v.particle_lifetime",
|
||||
"nodes": [1, 0]
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 1
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_point": {
|
||||
"direction": ["v.particle_random_1-0.5", "v.particle_random_2-0.25", -3]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": "math.random(0.3, 0.6)"
|
||||
},
|
||||
"minecraft:particle_initial_spin": {
|
||||
"rotation": "math.round(v.particle_random_4*3)*90"
|
||||
},
|
||||
"minecraft:particle_initial_speed": 8,
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_acceleration": [0, -5, 0],
|
||||
"linear_drag_coefficient": 8
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": ["0.22 * variable.scale", "0.22 * variable.scale"],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 8,
|
||||
"texture_height": 56,
|
||||
"flipbook": {
|
||||
"base_UV": [0, 24],
|
||||
"size_UV": [8, 8],
|
||||
"step_UV": [0, 8],
|
||||
"frames_per_second": 16,
|
||||
"max_frame": 4
|
||||
}
|
||||
}
|
||||
},
|
||||
"minecraft:particle_motion_collision": {
|
||||
"collision_radius": 0.02
|
||||
},
|
||||
"minecraft:particle_appearance_tinting": {
|
||||
"color": [0.61176, 0.87451, 1, 1]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
{
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:watershuriken_actorvert",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_blend",
|
||||
"texture": "textures/particles/moves/watershuriken"
|
||||
}
|
||||
},
|
||||
"curves": {
|
||||
"variable.rsize": {
|
||||
"type": "linear",
|
||||
"input": "v.particle_age",
|
||||
"horizontal_range": "v.particle_lifetime",
|
||||
"nodes": [0, 1, 1, 1, 1, 1, 1, 1]
|
||||
}
|
||||
},
|
||||
"events": {
|
||||
"trail": {
|
||||
"particle_effect": {
|
||||
"effect": "cobblemon:watershuriken_actortrail",
|
||||
"type": "particle"
|
||||
}
|
||||
},
|
||||
"hit": {
|
||||
"particle_effect": {
|
||||
"effect": "cobblemon:watershuriken_target",
|
||||
"type": "particle"
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_initialization": {
|
||||
"creation_expression": "v.target_deltaz=5;"
|
||||
},
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 1
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 0.25
|
||||
},
|
||||
"minecraft:emitter_shape_disc": {
|
||||
"offset": [0, 0.02, 0.1],
|
||||
"radius": 0.5,
|
||||
"direction": "outwards"
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": 0.35
|
||||
},
|
||||
"minecraft:particle_lifetime_events": {
|
||||
"timeline": {
|
||||
"0.00": "trail",
|
||||
"0.06": "trail",
|
||||
"0.12": "trail",
|
||||
"0.18": "trail",
|
||||
"0.24": "trail",
|
||||
"0.30": "trail",
|
||||
"0.34": "hit"
|
||||
}
|
||||
},
|
||||
"minecraft:particle_initial_spin": {
|
||||
"rotation": "math.random_integer(0,3)*90"
|
||||
},
|
||||
"minecraft:particle_motion_parametric": {
|
||||
"relative_position": ["-v.target_deltax*(v.particle_age / v.particle_lifetime)", "(v.target_deltay*(v.particle_age / v.particle_lifetime))", "-v.target_deltaz*(v.particle_age / v.particle_lifetime)"]
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": ["0.4*v.rsize", "0.4*v.rsize"],
|
||||
"facing_camera_mode": "emitter_transform_yz",
|
||||
"uv": {
|
||||
"texture_width": 60,
|
||||
"texture_height": 15,
|
||||
"flipbook": {
|
||||
"base_UV": [0, 0],
|
||||
"size_UV": [15, 15],
|
||||
"step_UV": [15, 0],
|
||||
"frames_per_second": 24,
|
||||
"max_frame": 4,
|
||||
"loop": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
{
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:watershuriken_target",
|
||||
"basic_render_parameters": {
|
||||
"material": "particles_alpha",
|
||||
"texture": "textures/particles/generic/impact/impact_water"
|
||||
}
|
||||
},
|
||||
"curves": {
|
||||
"variable.scale": {
|
||||
"type": "linear",
|
||||
"input": "v.particle_age",
|
||||
"horizontal_range": "v.particle_lifetime",
|
||||
"nodes": [1, 0]
|
||||
}
|
||||
},
|
||||
"events": {
|
||||
"event": {
|
||||
"particle_effect": {
|
||||
"effect": "cobblemon:watershuriken_targetspark",
|
||||
"type": "particle"
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_steady": {
|
||||
"spawn_rate": 240,
|
||||
"max_particles": 14
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 0.1
|
||||
},
|
||||
"minecraft:emitter_lifetime_events": {
|
||||
"creation_event": "event"
|
||||
},
|
||||
"minecraft:emitter_shape_point": {},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": "math.random(0.3, 0.6)"
|
||||
},
|
||||
"minecraft:particle_initial_spin": {
|
||||
"rotation": "math.round(v.particle_random_4*3)*90"
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(9,17)",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_drag_coefficient": 5
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": ["0.3 * variable.scale", "0.3 * variable.scale"],
|
||||
"facing_camera_mode": "rotate_xyz",
|
||||
"uv": {
|
||||
"texture_width": 8,
|
||||
"texture_height": 56,
|
||||
"flipbook": {
|
||||
"base_UV": [0, 16],
|
||||
"size_UV": [8, 8],
|
||||
"step_UV": [0, 8],
|
||||
"frames_per_second": 16,
|
||||
"max_frame": 5
|
||||
}
|
||||
}
|
||||
},
|
||||
"minecraft:particle_appearance_tinting": {
|
||||
"color": [0.61176, 0.87451, 1, 1]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
{
|
||||
"format_version": "1.10.0",
|
||||
"particle_effect": {
|
||||
"description": {
|
||||
"identifier": "cobblemon:watershuriken_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, 1, 0.88, 0.66, 0.35, -0.05]
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"minecraft:emitter_rate_instant": {
|
||||
"num_particles": 7
|
||||
},
|
||||
"minecraft:emitter_lifetime_once": {
|
||||
"active_time": 1
|
||||
},
|
||||
"minecraft:emitter_shape_point": {
|
||||
"offset": [0, 0, -0.25],
|
||||
"direction": ["v.particle_random_1-0.5", "v.particle_random_2-0.25", "v.particle_random_3-0.5"]
|
||||
},
|
||||
"minecraft:particle_lifetime_expression": {
|
||||
"max_lifetime": "0.5-(v.particle_random_4*0.1)"
|
||||
},
|
||||
"minecraft:particle_initial_speed": "math.random(1.75,3.55)*3",
|
||||
"minecraft:particle_motion_dynamic": {
|
||||
"linear_acceleration": [0, -5, 0],
|
||||
"linear_drag_coefficient": 4
|
||||
},
|
||||
"minecraft:particle_appearance_billboard": {
|
||||
"size": ["0.125*v.bitespark", "0.125*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
|
||||
},
|
||||
"minecraft:particle_appearance_tinting": {
|
||||
"color": {
|
||||
"interpolant": "v.particle_age / v.particle_lifetime",
|
||||
"gradient": {
|
||||
"0.0": "#FF51D8FF",
|
||||
"1.0": "#FF0076FF"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
@@ -1815,6 +1815,12 @@
|
||||
"wings_open": {
|
||||
"scale": 0
|
||||
}
|
||||
},
|
||||
"timeline": {
|
||||
"0.0": "q.run_molang('cobblemon:stepsound_claw_medium');",
|
||||
"0.5": "q.run_molang('cobblemon:stepsound_claw_medium');",
|
||||
"1.0": "q.run_molang('cobblemon:stepsound_claw_medium');",
|
||||
"1.5": "q.run_molang('cobblemon:stepsound_claw_medium');"
|
||||
}
|
||||
},
|
||||
"animation.pidgeot.mount_ground_idle": {
|
||||
@@ -3631,6 +3637,12 @@
|
||||
"wings_open": {
|
||||
"scale": 0
|
||||
}
|
||||
},
|
||||
"timeline": {
|
||||
"0.0": "q.run_molang('cobblemon:stepsound_claw_medium');",
|
||||
"0.5": "q.run_molang('cobblemon:stepsound_claw_medium');",
|
||||
"1.0": "q.run_molang('cobblemon:stepsound_claw_medium');",
|
||||
"1.5": "q.run_molang('cobblemon:stepsound_claw_medium');"
|
||||
}
|
||||
},
|
||||
"animation.pidgeot.ride_ground_walk": {
|
||||
|
||||
+611
-9
@@ -37,10 +37,10 @@
|
||||
"rotation": [0, -7.5, 0]
|
||||
},
|
||||
"tail2": {
|
||||
"rotation": [30, 0, 0]
|
||||
"rotation": ["30-math.sin(q.anim_time*90*2-60)*-3", 0, 0]
|
||||
},
|
||||
"tail3": {
|
||||
"rotation": [12.5, 0, 0]
|
||||
"rotation": ["12.5-math.sin(q.anim_time*90*2-120)*-3", 0, 0]
|
||||
},
|
||||
"leg_right": {
|
||||
"rotation": [0, 5, 0]
|
||||
@@ -53,6 +53,22 @@
|
||||
},
|
||||
"wings_open": {
|
||||
"scale": 0
|
||||
},
|
||||
"torso": {
|
||||
"rotation": ["-math.sin(q.anim_time*90*2-90)*1", 0, "math.sin(q.anim_time*90*1-90)*1"],
|
||||
"position": [0, "math.sin(q.anim_time*90*2)*0.1", 0]
|
||||
},
|
||||
"wing_closed_left": {
|
||||
"rotation": ["-0-math.sin(q.anim_time*90*2-150)*1", 0, 0]
|
||||
},
|
||||
"wing_closed_right": {
|
||||
"rotation": ["-0-math.sin(q.anim_time*90*2-150)*1", 0, 0]
|
||||
},
|
||||
"neck": {
|
||||
"rotation": ["-math.sin(q.anim_time*90*2-180)*1", 0, 0]
|
||||
},
|
||||
"head": {
|
||||
"rotation": ["-math.sin(q.anim_time*90*2-90)*-2", 0, "math.sin(q.anim_time*90*1-60)*-1"]
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -111,6 +127,30 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"torso": {
|
||||
"rotation": {
|
||||
"0.0": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.3333": {
|
||||
"post": [5, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.5833": {
|
||||
"post": [2.5, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.8333": {
|
||||
"post": [-5, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.1667": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
}
|
||||
}
|
||||
},
|
||||
"jaw": {
|
||||
"rotation": {
|
||||
"0.0": {
|
||||
@@ -118,19 +158,15 @@
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.1667": {
|
||||
"post": [85, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.4167": {
|
||||
"post": [85, 0, 0],
|
||||
"post": [72.5, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.5833": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.75": {
|
||||
"post": [85, 0, 0],
|
||||
"0.8333": {
|
||||
"post": [52.5, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.1667": {
|
||||
@@ -138,6 +174,32 @@
|
||||
"lerp_mode": "catmullrom"
|
||||
}
|
||||
}
|
||||
},
|
||||
"eyelid_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.5833": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0.1, 0, -0.1]
|
||||
},
|
||||
"0.75": {
|
||||
"pre": [0.1, 0, -0.1],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"eyelid_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.5833": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [-0.1, 0, -0.1]
|
||||
},
|
||||
"0.75": {
|
||||
"pre": [-0.1, 0, -0.1],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"sound_effects": {
|
||||
@@ -203,6 +265,546 @@
|
||||
"position": [-0.1, 0, -0.1]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.spearow.hold_item": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"jaw": {
|
||||
"rotation": [30, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.spearow.ground_walk": {
|
||||
"loop": true,
|
||||
"animation_length": 0.75,
|
||||
"bones": {
|
||||
"torso": {
|
||||
"rotation": ["1-math.cos(q.anim_time*90*16/3*2)*-2", "-math.sin(q.anim_time*90*16/3+60)*3", "-1+math.sin(q.anim_time*90*16/3+30)*-4"],
|
||||
"position": [0, "math.sin(q.anim_time*90*16/3*2)*0.2", 0]
|
||||
},
|
||||
"wings_open": {
|
||||
"scale": 0
|
||||
},
|
||||
"wing_closed_left": {
|
||||
"rotation": [3, 0, 0]
|
||||
},
|
||||
"wing_closed_right": {
|
||||
"rotation": [3, 0, 0]
|
||||
},
|
||||
"tail2": {
|
||||
"rotation": ["22-math.cos(q.anim_time*90*16/3*2)*5", 0, 0]
|
||||
},
|
||||
"tail3": {
|
||||
"rotation": ["5-math.cos(q.anim_time*90*16/3*2)*5", 0, 0]
|
||||
},
|
||||
"neck": {
|
||||
"rotation": {
|
||||
"0.0": ["-math.cos(q.anim_time*90*16/3*2)*-12.5", "-math.sin(q.anim_time*90*16/3+60)*-3", "math.sin(q.anim_time*90*16/3+30)*3"],
|
||||
"0.125": ["-math.cos(q.anim_time*90*16/3*2)*-9.5", "-math.sin(q.anim_time*90*16/3+60)*-3", "math.sin(q.anim_time*90*16/3+30)*3"],
|
||||
"0.1667": ["-math.cos(q.anim_time*90*16/3*2)*-12.5", "-math.sin(q.anim_time*90*16/3+60)*-3", "math.sin(q.anim_time*90*16/3+30)*3"],
|
||||
"0.375": ["-math.cos(q.anim_time*90*16/3*2)*-12.5", "-math.sin(q.anim_time*90*16/3+60)*-3", "math.sin(q.anim_time*90*16/3+30)*3"],
|
||||
"0.5": ["-math.cos(q.anim_time*90*16/3*2)*-9.5", "-math.sin(q.anim_time*90*16/3+60)*-3", "math.sin(q.anim_time*90*16/3+30)*3"],
|
||||
"0.5417": ["-math.cos(q.anim_time*90*16/3*2)*-12.5", "-math.sin(q.anim_time*90*16/3+60)*-3", "math.sin(q.anim_time*90*16/3+30)*3"]
|
||||
},
|
||||
"position": {
|
||||
"0.0": [0, "math.cos(q.anim_time*90*16/3*2)*0.2", 0],
|
||||
"0.0417": [0, -0.075, 0.025],
|
||||
"0.0833": [0, "-0.2+math.cos(q.anim_time*90*16/3*2)*0.2", -0.2],
|
||||
"0.125": [0, -0.22, -0.17],
|
||||
"0.1667": [0, -0.21, -0.185],
|
||||
"0.375": [0, "math.cos(q.anim_time*90*16/3*2)*0.2", 0],
|
||||
"0.4167": [0, -0.075, 0.025],
|
||||
"0.4583": [0, "-0.2+math.cos(q.anim_time*90*16/3*2)*0.2", -0.2],
|
||||
"0.5": [0, -0.22, -0.17],
|
||||
"0.5417": [0, -0.21, -0.185],
|
||||
"0.75": [0, "math.cos(q.anim_time*90*16/3*2)*0.2", 0]
|
||||
}
|
||||
},
|
||||
"head": {
|
||||
"rotation": ["5-math.cos(q.anim_time*90*16/3*2)*18", 0, 0],
|
||||
"position": [0, 0, "-0.2+math.cos(q.anim_time*90*16/3*2)*0.3"]
|
||||
},
|
||||
"scruff_left": {
|
||||
"rotation": [0, "-0-math.cos(q.anim_time*90*16/3*2-30)*7", 0]
|
||||
},
|
||||
"scruff_right": {
|
||||
"rotation": [0, "0+math.cos(q.anim_time*90*16/3*2-30)*7", 0]
|
||||
},
|
||||
"scruff_top_right": {
|
||||
"rotation": ["-0-math.cos(q.anim_time*90*16/3*2-30)*5", 0, 0]
|
||||
},
|
||||
"scruff_bottom": {
|
||||
"rotation": ["-0-math.cos(q.anim_time*90*16/3*2)*-12", 0, 0]
|
||||
},
|
||||
"leg_left": {
|
||||
"rotation": {
|
||||
"0.0": [25, -17.5, 0],
|
||||
"0.125": {
|
||||
"pre": [21.25, -12.5, 0],
|
||||
"post": [21.25, -12.5, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.375": [-40, -5, 0],
|
||||
"0.75": [25, -17.5, 0]
|
||||
},
|
||||
"position": {
|
||||
"0.0": [0.3, 0.1, 0.6],
|
||||
"0.0417": [0.23, 0.25, 0.71],
|
||||
"0.125": {
|
||||
"pre": [0, 0.68, -0.08],
|
||||
"post": [0, 0.68, -0.08],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.25": {
|
||||
"post": [0, 0.97, -1.41],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.375": [0, -0.5, -2.15],
|
||||
"0.5": [0, -0.19, -1.02],
|
||||
"0.5833": [0, -0.07, -0.3],
|
||||
"0.625": [0, -0.02, 0.21],
|
||||
"0.7083": [0.1, 0.215, 0.43],
|
||||
"0.75": [0.3, 0.1, 0.6]
|
||||
}
|
||||
},
|
||||
"leg_left2": {
|
||||
"rotation": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.125": {
|
||||
"pre": [-30.83, 0, 0],
|
||||
"post": [-30.83, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.25": {
|
||||
"post": [-2.65, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.375": [12.5, 0, 0],
|
||||
"0.75": [0, 0, 0]
|
||||
}
|
||||
},
|
||||
"foot_left": {
|
||||
"rotation": {
|
||||
"0.0": [27.5, 0, -5],
|
||||
"0.125": {
|
||||
"pre": [20.17, 0, 0],
|
||||
"post": [20.17, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.25": {
|
||||
"post": [12.596, 0.6637, -1.3486],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.375": [28, 0, 0],
|
||||
"0.625": [-7.33, 0, 0],
|
||||
"0.75": [27.5, 0, -5]
|
||||
},
|
||||
"position": {
|
||||
"0.0": [0, 0.25, 0],
|
||||
"0.125": [0, 0, 0],
|
||||
"0.375": [0, 0, 0],
|
||||
"0.625": [0, 0.17, 0],
|
||||
"0.75": [0, 0.25, 0]
|
||||
}
|
||||
},
|
||||
"toe_back_left": {
|
||||
"rotation": {
|
||||
"0.0": [-20, 0, 0],
|
||||
"0.2083": {
|
||||
"pre": [-8.33, 0, 0],
|
||||
"post": [-8.33, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.375": [0, 0, 0],
|
||||
"0.625": [0, 0, 0],
|
||||
"0.75": [-20, 0, 0]
|
||||
}
|
||||
},
|
||||
"toe_inner_left": {
|
||||
"rotation": {
|
||||
"0.0": [-55, 10, -7.5],
|
||||
"0.125": {
|
||||
"pre": [7.5, 15, 0],
|
||||
"post": [7.5, 15, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.25": {
|
||||
"post": [5, 15, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.375": [0, 15, 0],
|
||||
"0.625": [0, 15, 0],
|
||||
"0.75": [-55, 10, -7.5]
|
||||
},
|
||||
"position": {
|
||||
"0.0": [0, -0.75, 1.35],
|
||||
"0.125": [0, 0, 0],
|
||||
"0.625": [0, 0, 0],
|
||||
"0.75": [0, -0.75, 1.35]
|
||||
}
|
||||
},
|
||||
"toe_outer_left": {
|
||||
"rotation": {
|
||||
"0.0": [-51.5, -2.5, 10],
|
||||
"0.125": {
|
||||
"pre": [5, -15, 0],
|
||||
"post": [5, -15, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.25": {
|
||||
"post": [5, -15, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.375": [0, -15, 0],
|
||||
"0.625": [0, -15, 0],
|
||||
"0.75": [-51.5, -2.5, 10]
|
||||
},
|
||||
"position": {
|
||||
"0.0": [0, -0.75, 1.35],
|
||||
"0.125": [0, 0, 0],
|
||||
"0.625": [0, 0, 0],
|
||||
"0.75": [0, -0.75, 1.35]
|
||||
}
|
||||
},
|
||||
"leg_right": {
|
||||
"rotation": {
|
||||
"0.0": [-40, 5, 0],
|
||||
"0.375": [25, 17.5, 0],
|
||||
"0.5": {
|
||||
"pre": [21.25, 12.5, 0],
|
||||
"post": [21.25, 12.5, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.75": [-40, 5, 0]
|
||||
},
|
||||
"position": {
|
||||
"0.0": [0, -0.5, -2.15],
|
||||
"0.125": [0, -0.19, -1.02],
|
||||
"0.2083": [0, -0.07, -0.3],
|
||||
"0.25": [0, -0.02, 0.21],
|
||||
"0.3333": [-0.1, 0.215, 0.43],
|
||||
"0.375": [-0.3, 0.1, 0.6],
|
||||
"0.4167": [-0.23, 0.25, 0.71],
|
||||
"0.5": {
|
||||
"pre": [0, 0.68, -0.08],
|
||||
"post": [0, 0.68, -0.08],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.625": {
|
||||
"post": [0, 0.97, -1.41],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.75": [0, -0.5, -2.15]
|
||||
}
|
||||
},
|
||||
"leg_right2": {
|
||||
"rotation": {
|
||||
"0.0": [12.5, 0, 0],
|
||||
"0.375": [0, 0, 0],
|
||||
"0.5": {
|
||||
"pre": [-30.83, 0, 0],
|
||||
"post": [-30.83, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.625": {
|
||||
"post": [-2.65, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.75": [12.5, 0, 0]
|
||||
}
|
||||
},
|
||||
"foot_right": {
|
||||
"rotation": {
|
||||
"0.0": [28, 0, 0],
|
||||
"0.25": [-7.33, 0, 0],
|
||||
"0.375": [27.5, 0, 5],
|
||||
"0.5": {
|
||||
"pre": [20.17, 0, 0],
|
||||
"post": [20.17, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.625": {
|
||||
"post": [12.596, -0.6637, 1.3486],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.75": [28, 0, 0]
|
||||
},
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.25": [0, 0.17, 0],
|
||||
"0.375": [0, 0.25, 0],
|
||||
"0.5": [0, 0, 0],
|
||||
"0.75": [0, 0, 0]
|
||||
}
|
||||
},
|
||||
"toe_back_right": {
|
||||
"rotation": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.25": [0, 0, 0],
|
||||
"0.375": [-20, 0, 0],
|
||||
"0.5833": {
|
||||
"pre": [-8.33, 0, 0],
|
||||
"post": [-8.33, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.75": [0, 0, 0]
|
||||
}
|
||||
},
|
||||
"toe_inner_right": {
|
||||
"rotation": {
|
||||
"0.0": [0, -15, 0],
|
||||
"0.25": [0, -15, 0],
|
||||
"0.375": [-55, -10, 7.5],
|
||||
"0.5": {
|
||||
"pre": [7.5, -15, 0],
|
||||
"post": [7.5, -15, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.625": {
|
||||
"post": [5, -15, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.75": [0, -15, 0]
|
||||
},
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.25": [0, 0, 0],
|
||||
"0.375": [0, -0.75, 1.35],
|
||||
"0.5": [0, 0, 0],
|
||||
"0.75": [0, 0, 0]
|
||||
}
|
||||
},
|
||||
"toe_outer_right": {
|
||||
"rotation": {
|
||||
"0.0": [0, 15, 0],
|
||||
"0.25": [0, 15, 0],
|
||||
"0.375": [-51.5, 2.5, -10],
|
||||
"0.5": {
|
||||
"pre": [5, 15, 0],
|
||||
"post": [5, 15, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.625": {
|
||||
"post": [5, 15, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.75": [0, 15, 0]
|
||||
},
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.25": [0, 0, 0],
|
||||
"0.375": [0, -0.75, 1.35],
|
||||
"0.5": [0, 0, 0],
|
||||
"0.75": [0, 0, 0]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.spearow.air_idle": {
|
||||
"loop": true,
|
||||
"animation_length": 4,
|
||||
"bones": {
|
||||
"body": {
|
||||
"position": ["-math.sin(q.anim_time*90*3-45)*0.5", "math.sin(q.anim_time*90*6-45)*1.5", "math.sin(q.anim_time*90*6-45)*1/2"]
|
||||
},
|
||||
"torso": {
|
||||
"rotation": ["-math.sin(q.anim_time*90*6-120)*-4", 0, "math.sin(q.anim_time*90*3-90)*4"]
|
||||
},
|
||||
"wing_open_left": {
|
||||
"rotation": ["-math.sin(q.anim_time*90*6-90)*6", 0, "math.sin(q.anim_time*90*6)*65"],
|
||||
"position": [0, "math.sin(q.anim_time*90*6)*-1", 0]
|
||||
},
|
||||
"wing_open_left2": {
|
||||
"rotation": [0, 0, "20+math.sin(q.anim_time*90*6-45)*30"]
|
||||
},
|
||||
"wing_open_left3": {
|
||||
"rotation": [0, 0, "0+math.sin(q.anim_time*90*6-75)*30"]
|
||||
},
|
||||
"wing_open_right": {
|
||||
"rotation": ["-math.sin(q.anim_time*90*6-90)*6", 0, "-math.sin(q.anim_time*90*6)*65"],
|
||||
"position": [0, "math.sin(q.anim_time*90*6)*-1", 0]
|
||||
},
|
||||
"wing_open_right2": {
|
||||
"rotation": [0, 0, "-20-math.sin(q.anim_time*90*6-45)*30"]
|
||||
},
|
||||
"wing_open_right3": {
|
||||
"rotation": [0, 0, "-0-math.sin(q.anim_time*90*6-75)*30"]
|
||||
},
|
||||
"tail2": {
|
||||
"rotation": ["-math.sin(q.anim_time*90*6-30)*5", 0, 0]
|
||||
},
|
||||
"tail3": {
|
||||
"rotation": ["-math.sin(q.anim_time*90*6-90)*5", 0, 0]
|
||||
},
|
||||
"neck": {
|
||||
"rotation": ["5-math.sin(q.anim_time*90*6-140)*-1", 0, "math.sin(q.anim_time*90*3-00)*-1"]
|
||||
},
|
||||
"head": {
|
||||
"rotation": ["-math.sin(q.anim_time*90*6-110)*3", 0, "math.sin(q.anim_time*90*3-120)*-2"]
|
||||
},
|
||||
"scruff_left": {
|
||||
"rotation": [0, "-0-math.sin(q.anim_time*90*6-170)*4", 0]
|
||||
},
|
||||
"scruff_right": {
|
||||
"rotation": [0, "0+math.sin(q.anim_time*90*6-170)*4", 0]
|
||||
},
|
||||
"scruff_top_right": {
|
||||
"rotation": ["-0-math.sin(q.anim_time*90*6-210)*6", 0, 0]
|
||||
},
|
||||
"scruff_bottom": {
|
||||
"rotation": ["-0-math.sin(q.anim_time*90*6-170)*3", 0, 0]
|
||||
},
|
||||
"leg_left": {
|
||||
"rotation": [50, 0, 0]
|
||||
},
|
||||
"leg_left2": {
|
||||
"rotation": [-100, 0, 0]
|
||||
},
|
||||
"foot_left": {
|
||||
"rotation": ["40-math.sin(q.anim_time*90*6-30)*-5", -10, "math.sin(q.anim_time*90*3-150)*6"]
|
||||
},
|
||||
"toe_back_left": {
|
||||
"rotation": [-27.5, 0, 0]
|
||||
},
|
||||
"toe_inner_left": {
|
||||
"rotation": [37.5, 0, 0]
|
||||
},
|
||||
"toe_outer_left": {
|
||||
"rotation": [37.5, 0, 0]
|
||||
},
|
||||
"leg_right": {
|
||||
"rotation": [50, 0, 0]
|
||||
},
|
||||
"leg_right2": {
|
||||
"rotation": [-100, 0, 0]
|
||||
},
|
||||
"foot_right": {
|
||||
"rotation": ["40-math.sin(q.anim_time*90*6-30)*-5", 10, "-math.sin(q.anim_time*90*3-150)*6"]
|
||||
},
|
||||
"toe_back_right": {
|
||||
"rotation": [-27.5, 0, 0]
|
||||
},
|
||||
"toe_inner_right": {
|
||||
"rotation": [37.5, 0, 0]
|
||||
},
|
||||
"toe_outer_right": {
|
||||
"rotation": [37.5, 0, 0]
|
||||
}
|
||||
},
|
||||
"timeline": {
|
||||
"0.6667": "q.has_entity?{q.sound('animation.plumage.wing_flap.small');};",
|
||||
"1.3333": "q.has_entity?{q.sound('animation.plumage.wing_flap.small');};",
|
||||
"2.0": "q.has_entity?{q.sound('animation.plumage.wing_flap.small');};",
|
||||
"2.6667": "q.has_entity?{q.sound('animation.plumage.wing_flap.small');};",
|
||||
"3.3333": "q.has_entity?{q.sound('animation.plumage.wing_flap.small');};",
|
||||
"4.0": "q.has_entity?{q.sound('animation.plumage.wing_flap.small');};"
|
||||
}
|
||||
},
|
||||
"animation.spearow.air_fly": {
|
||||
"loop": true,
|
||||
"animation_length": 4,
|
||||
"bones": {
|
||||
"body": {
|
||||
"position": ["-math.sin(q.anim_time*90*3-45)*0.5", "math.sin(q.anim_time*90*6-45)*1.5", "math.sin(q.anim_time*90*6-45)*1/2"]
|
||||
},
|
||||
"torso": {
|
||||
"rotation": ["15-math.sin(q.anim_time*90*6-120)*-1.5", 0, "math.sin(q.anim_time*90*3-90)*4"]
|
||||
},
|
||||
"wing_open_left": {
|
||||
"rotation": ["-math.sin(q.anim_time*90*6-90)*6", 0, "math.sin(q.anim_time*90*6)*65"],
|
||||
"position": [0, "math.sin(q.anim_time*90*6)*-1", 0]
|
||||
},
|
||||
"wing_open_left2": {
|
||||
"rotation": [0, 0, "20+math.sin(q.anim_time*90*6-45)*30"]
|
||||
},
|
||||
"wing_open_left3": {
|
||||
"rotation": [0, 0, "0+math.sin(q.anim_time*90*6-75)*30"]
|
||||
},
|
||||
"wing_open_right": {
|
||||
"rotation": ["-math.sin(q.anim_time*90*6-90)*6", 0, "-math.sin(q.anim_time*90*6)*65"],
|
||||
"position": [0, "math.sin(q.anim_time*90*6)*-1", 0]
|
||||
},
|
||||
"wing_open_right2": {
|
||||
"rotation": [0, 0, "-20-math.sin(q.anim_time*90*6-45)*30"]
|
||||
},
|
||||
"wing_open_right3": {
|
||||
"rotation": [0, 0, "-0-math.sin(q.anim_time*90*6-75)*30"]
|
||||
},
|
||||
"tail": {
|
||||
"rotation": [-10, 0, 0]
|
||||
},
|
||||
"tail2": {
|
||||
"rotation": ["-math.sin(q.anim_time*90*6-30)*5", 0, 0]
|
||||
},
|
||||
"tail3": {
|
||||
"rotation": ["-math.sin(q.anim_time*90*6-90)*5", 0, 0]
|
||||
},
|
||||
"neck": {
|
||||
"rotation": ["5-math.sin(q.anim_time*90*6-140)*-1", 0, "math.sin(q.anim_time*90*3-00)*-1"]
|
||||
},
|
||||
"head_ai": {
|
||||
"rotation": [5, 0, 0]
|
||||
},
|
||||
"head": {
|
||||
"rotation": ["-7.5-math.sin(q.anim_time*90*6-110)*3", 0, "math.sin(q.anim_time*90*3-120)*-2"]
|
||||
},
|
||||
"scruff_left": {
|
||||
"rotation": [0, "-0-math.sin(q.anim_time*90*6-170)*4", 0]
|
||||
},
|
||||
"scruff_right": {
|
||||
"rotation": [0, "0+math.sin(q.anim_time*90*6-170)*4", 0]
|
||||
},
|
||||
"scruff_top_right": {
|
||||
"rotation": ["-0-math.sin(q.anim_time*90*6-210)*6", 0, 0]
|
||||
},
|
||||
"scruff_bottom": {
|
||||
"rotation": ["-0-math.sin(q.anim_time*90*6-170)*3", 0, 0]
|
||||
},
|
||||
"leg_left": {
|
||||
"rotation": [50, 0, 0]
|
||||
},
|
||||
"leg_left2": {
|
||||
"rotation": [-100, 0, 0]
|
||||
},
|
||||
"foot_left": {
|
||||
"rotation": ["40-math.sin(q.anim_time*90*6-30)*-5", -10, "math.sin(q.anim_time*90*3-150)*6"]
|
||||
},
|
||||
"toe_back_left": {
|
||||
"rotation": [-27.5, 0, 0]
|
||||
},
|
||||
"toe_inner_left": {
|
||||
"rotation": [37.5, 0, 0]
|
||||
},
|
||||
"toe_outer_left": {
|
||||
"rotation": [37.5, 0, 0]
|
||||
},
|
||||
"leg_right": {
|
||||
"rotation": [50, 0, 0]
|
||||
},
|
||||
"leg_right2": {
|
||||
"rotation": [-100, 0, 0]
|
||||
},
|
||||
"foot_right": {
|
||||
"rotation": ["40-math.sin(q.anim_time*90*6-30)*-5", 10, "-math.sin(q.anim_time*90*3-150)*6"]
|
||||
},
|
||||
"toe_back_right": {
|
||||
"rotation": [-27.5, 0, 0]
|
||||
},
|
||||
"toe_inner_right": {
|
||||
"rotation": [37.5, 0, 0]
|
||||
},
|
||||
"toe_outer_right": {
|
||||
"rotation": [37.5, 0, 0]
|
||||
}
|
||||
},
|
||||
"timeline": {
|
||||
"0.6667": "q.has_entity?{q.sound('animation.plumage.wing_flap.small');};",
|
||||
"1.3333": "q.has_entity?{q.sound('animation.plumage.wing_flap.small');};",
|
||||
"2.0": "q.has_entity?{q.sound('animation.plumage.wing_flap.small');};",
|
||||
"2.6667": "q.has_entity?{q.sound('animation.plumage.wing_flap.small');};",
|
||||
"3.3333": "q.has_entity?{q.sound('animation.plumage.wing_flap.small');};",
|
||||
"4.0": "q.has_entity?{q.sound('animation.plumage.wing_flap.small');};"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+3331
-67
File diff suppressed because it is too large.
Load diff
+464
-58
@@ -2,6 +2,312 @@
|
||||
"format_version": "1.8.0",
|
||||
"animations": {
|
||||
"animation.ninetales.ground_idle": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"body": {
|
||||
"position": [0, -0.3, 0]
|
||||
},
|
||||
"torso": {
|
||||
"rotation": ["5+math.sin(q.anim_time*90*1-0)*0.5", 0, "0-math.sin(q.anim_time*90*0.5-30)*0.5"]
|
||||
},
|
||||
"chest": {
|
||||
"rotation": ["-4.8+math.sin(q.anim_time*90*1-30)*0.5", 0, -1.2]
|
||||
},
|
||||
"neck": {
|
||||
"rotation": ["-12.5+math.sin(q.anim_time*90*1-60)*1", 0, 0]
|
||||
},
|
||||
"neck_fur_left2": {
|
||||
"rotation": [0, 0, "-7.5-math.sin(q.anim_time*90*1-90)*1"]
|
||||
},
|
||||
"neck_fur_right2": {
|
||||
"rotation": [0, 0, "7.5+math.sin(q.anim_time*90*1-90)*1"]
|
||||
},
|
||||
"neck2": {
|
||||
"rotation": ["-12.5+math.sin(q.anim_time*90*1-90)*0.5", 0, 0]
|
||||
},
|
||||
"head_rotation": {
|
||||
"rotation": ["32.5+math.sin(q.anim_time*90*1-90)*-2", 0, "0-math.sin(q.anim_time*90*1-120)*-0.5"]
|
||||
},
|
||||
"hair2": {
|
||||
"rotation": ["-2.5+math.sin(q.anim_time*90*1-210)*1", 0, 0]
|
||||
},
|
||||
"hair_back_top": {
|
||||
"rotation": ["-2.5+math.sin(q.anim_time*90*1-300)*2", 0, 0]
|
||||
},
|
||||
"hair_back_top2": {
|
||||
"rotation": ["-22.5+math.sin(q.anim_time*90*1-360)*4", 0, 0]
|
||||
},
|
||||
"hair_back_bottom2": {
|
||||
"rotation": ["-20+math.sin(q.anim_time*90*1-380)*4", 0, 0]
|
||||
},
|
||||
"tail_middle": {
|
||||
"rotation": ["42.5+math.sin(q.anim_time*90*1-60)*-0.5", 0, 0]
|
||||
},
|
||||
"tail_middle2": {
|
||||
"rotation": ["7.5+math.sin(q.anim_time*90*1-120)*-1", 0, 0]
|
||||
},
|
||||
"tail_middle3": {
|
||||
"rotation": ["17.5+math.sin(q.anim_time*90*1-180)*-1", 0, 0]
|
||||
},
|
||||
"tail_middle4": {
|
||||
"rotation": ["-37.5+math.sin(q.anim_time*90*1-240)*-4", 0, 0]
|
||||
},
|
||||
"tail_middle5": {
|
||||
"rotation": ["-35+math.sin(q.anim_time*90*1-300)*-6", 2.5, 0]
|
||||
},
|
||||
"tail_middle6": {
|
||||
"rotation": ["-42.5+math.sin(q.anim_time*90*1-300)*-6", 0, 0]
|
||||
},
|
||||
"tail_middle7": {
|
||||
"rotation": ["-25+math.sin(q.anim_time*90*1-400)*-6", 0, 0]
|
||||
},
|
||||
"tail_middle8": {
|
||||
"rotation": ["35+math.sin(q.anim_time*90*1-460)*-12", 0, 0]
|
||||
},
|
||||
"tail_left1_rotation": {
|
||||
"rotation": ["27.525638448+math.sin(q.anim_time*90*1-60)*-0.5", 2.04767, 1.43455]
|
||||
},
|
||||
"tail_left1_2": {
|
||||
"rotation": ["15.013645339+math.sin(q.anim_time*90*1-120)*-1", 2.41476, 0.64743]
|
||||
},
|
||||
"tail_left1_3": {
|
||||
"rotation": ["17.5+math.sin(q.anim_time*90*1-180)*-1", 0, 0]
|
||||
},
|
||||
"tail_left1_4": {
|
||||
"rotation": ["-32.599068173+math.sin(q.anim_time*90*1-240)*-4", -4.21541, 2.69136]
|
||||
},
|
||||
"tail_left1_5": {
|
||||
"rotation": ["-37.605552+math.sin(q.anim_time*90*1-300)*-6", -3.9649, 3.04868]
|
||||
},
|
||||
"tail_left1_6": {
|
||||
"rotation": ["-40.107597848+math.sin(q.anim_time*90*1-360)*-4", 3.82821, -3.21873]
|
||||
},
|
||||
"tail_left1_7": {
|
||||
"rotation": ["-27.702122918+math.sin(q.anim_time*90*1-400)*-6", 6.64851, -3.47875]
|
||||
},
|
||||
"tail_left1_8": {
|
||||
"rotation": ["30.867477791+math.sin(q.anim_time*90*1-460)*-12", 12.95254, 7.63074]
|
||||
},
|
||||
"tail_left2_rotation": {
|
||||
"rotation": ["22.577335588+math.sin(q.anim_time*90*1-60)*-0.5", 4.61854, 1.91757]
|
||||
},
|
||||
"tail_left2_2": {
|
||||
"rotation": ["12.5+math.sin(q.anim_time*90*1-120)*-1", 0, 0]
|
||||
},
|
||||
"tail_left2_3": {
|
||||
"rotation": ["15+math.sin(q.anim_time*90*1-180)*-1", 0, 0]
|
||||
},
|
||||
"tail_left2_4": {
|
||||
"rotation": ["-20+math.sin(q.anim_time*90*1-240)*-4", 0, 0]
|
||||
},
|
||||
"tail_left2_5": {
|
||||
"rotation": ["-56.265008831+math.sin(q.anim_time*90*1-300)*-6", -9.93191, 14.48174]
|
||||
},
|
||||
"tail_left2_6": {
|
||||
"rotation": ["-37.158458405+math.sin(q.anim_time*90*1-300)*-6", 18.26883, -13.36473]
|
||||
},
|
||||
"tail_left2_7": {
|
||||
"rotation": ["33.125975871+math.sin(q.anim_time*90*1-360)*-12", 10.51794, 6.79286]
|
||||
},
|
||||
"tail_left3_rotation": {
|
||||
"rotation": ["10+math.sin(q.anim_time*90*1-60)*-0.5", 0, 0]
|
||||
},
|
||||
"tail_left3_2": {
|
||||
"rotation": ["22.577335588+math.sin(q.anim_time*90*1-120)*-1", 4.61854, 1.91757]
|
||||
},
|
||||
"tail_left3_3": {
|
||||
"rotation": ["10+math.sin(q.anim_time*90*1-180)*-1", 0, 0]
|
||||
},
|
||||
"tail_left3_4": {
|
||||
"rotation": ["-30+math.sin(q.anim_time*90*1-240)*-4", 0, 0]
|
||||
},
|
||||
"tail_left3_5": {
|
||||
"rotation": ["-27.860824367+math.sin(q.anim_time*90*1-300)*-6", -8.86042, 4.65468]
|
||||
},
|
||||
"tail_left3_6": {
|
||||
"rotation": ["-43.1852829+math.sin(q.anim_time*90*1-300)*-6", 9.18229, -8.51814]
|
||||
},
|
||||
"tail_left3_7": {
|
||||
"rotation": ["35.413183453+math.sin(q.anim_time*90*1-360)*-12", 8.17773, 5.77509]
|
||||
},
|
||||
"tail_right1_rotation": {
|
||||
"rotation": ["27.525638448+math.sin(q.anim_time*90*1-60)*-0.5", -2.04767, -1.43455]
|
||||
},
|
||||
"tail_right1_2": {
|
||||
"rotation": ["15.013645339+math.sin(q.anim_time*90*1-120)*-1", -2.41476, -0.64743]
|
||||
},
|
||||
"tail_right1_3": {
|
||||
"rotation": ["17.5+math.sin(q.anim_time*90*1-180)*-1", 0, 0]
|
||||
},
|
||||
"tail_right1_4": {
|
||||
"rotation": ["-32.599068173+math.sin(q.anim_time*90*1-240)*-4", 4.21541, -2.69136]
|
||||
},
|
||||
"tail_right1_5": {
|
||||
"rotation": ["-37.605552+math.sin(q.anim_time*90*1-300)*-6", 3.9649, -3.04868]
|
||||
},
|
||||
"tail_right1_6": {
|
||||
"rotation": ["-40.107597848+math.sin(q.anim_time*90*1-360)*-4", -3.82821, 3.21873]
|
||||
},
|
||||
"tail_right1_7": {
|
||||
"rotation": ["-27.702122918+math.sin(q.anim_time*90*1-400)*-6", -6.64851, 3.47875]
|
||||
},
|
||||
"tail_right1_8": {
|
||||
"rotation": ["30.867477791+math.sin(q.anim_time*90*1-460)*-12", -12.95254, -7.63074]
|
||||
},
|
||||
"tail_right2_rotation": {
|
||||
"rotation": ["22.577335588+math.sin(q.anim_time*90*1-60)*-0.5", -4.61854, -1.91757]
|
||||
},
|
||||
"tail_right2_2": {
|
||||
"rotation": ["12.5+math.sin(q.anim_time*90*1-120)*-1", 0, 0]
|
||||
},
|
||||
"tail_right2_3": {
|
||||
"rotation": ["15+math.sin(q.anim_time*90*1-180)*-1", 0, 0]
|
||||
},
|
||||
"tail_right2_4": {
|
||||
"rotation": ["-20+math.sin(q.anim_time*90*1-240)*-4", 0, 0]
|
||||
},
|
||||
"tail_right2_5": {
|
||||
"rotation": ["-56.265008831+math.sin(q.anim_time*90*1-300)*-6", 9.93191, -14.48174]
|
||||
},
|
||||
"tail_right2_6": {
|
||||
"rotation": ["-37.158458405+math.sin(q.anim_time*90*1-300)*-6", -18.26883, 13.36473]
|
||||
},
|
||||
"tail_right2_7": {
|
||||
"rotation": ["33.125975871+math.sin(q.anim_time*90*1-360)*-12", -10.51794, -6.79286]
|
||||
},
|
||||
"leg_front_left": {
|
||||
"rotation": ["-9.981069394+math.sin(q.anim_time*90*1-0)*-1", 0.43523, 4.98107],
|
||||
"position": [0, "0-math.sin(q.anim_time*90*1-0)*0.025", "0-math.sin(q.anim_time*90*1-0)*-0.15"]
|
||||
},
|
||||
"leg_front_left2": {
|
||||
"rotation": ["-2.5+math.sin(q.anim_time*90*1-0)*0.5", 0, 0]
|
||||
},
|
||||
"foot_front_left": {
|
||||
"rotation": ["12.5+math.sin(q.anim_time*90*1-0)*0.5", 0, -5]
|
||||
},
|
||||
"leg_back_left": {
|
||||
"rotation": ["10+math.sin(q.anim_time*90*1-0)*1", 0, -7.5],
|
||||
"position": [0, "0-math.sin(q.anim_time*90*1-0)*0.2", "0-math.sin(q.anim_time*90*1-0)*0.25"]
|
||||
},
|
||||
"leg_back_left2": {
|
||||
"rotation": ["-2.5+math.sin(q.anim_time*90*1-0)*1", 0, 0]
|
||||
},
|
||||
"leg_back_left3": {
|
||||
"rotation": ["-2.5+math.sin(q.anim_time*90*1-0)*-1", 0, 0]
|
||||
},
|
||||
"foot_back_left": {
|
||||
"rotation": ["-5+math.sin(q.anim_time*90*1-0)*-1", 0, 7.5]
|
||||
},
|
||||
"leg_front_right": {
|
||||
"rotation": ["10.018930606+math.sin(q.anim_time*90*1-0)*-1", -0.43523, -4.98107],
|
||||
"position": [0, "0-math.sin(q.anim_time*90*1-0)*0.025", "0-math.sin(q.anim_time*90*1-0)*-0.15"]
|
||||
},
|
||||
"leg_front_right2": {
|
||||
"rotation": ["-10+math.sin(q.anim_time*90*1-0)*0.5", 0, 0]
|
||||
},
|
||||
"foot_front_right": {
|
||||
"rotation": ["-0+math.sin(q.anim_time*90*1-0)*0.5", 0, 5]
|
||||
},
|
||||
"leg_back_right": {
|
||||
"rotation": ["17.521361057+math.sin(q.anim_time*90*1-0)*1", 0.32621, 7.49294],
|
||||
"position": [0, "0-math.sin(q.anim_time*90*1-0)*0.2", "0-math.sin(q.anim_time*90*1-0)*0.25"]
|
||||
},
|
||||
"leg_back_right2": {
|
||||
"rotation": ["-5+math.sin(q.anim_time*90*1-0)*1", 0, 0]
|
||||
},
|
||||
"leg_back_right3": {
|
||||
"rotation": ["2.5+math.sin(q.anim_time*90*1-0)*-1", 0, 0]
|
||||
},
|
||||
"foot_back_right": {
|
||||
"rotation": ["-15+math.sin(q.anim_time*90*1-0)*-1", 0, -7.5]
|
||||
},
|
||||
"tail_right3_rotation": {
|
||||
"rotation": ["10+math.sin(q.anim_time*90*1-60)*-0.5", 0, 0]
|
||||
},
|
||||
"tail_right3_2": {
|
||||
"rotation": ["22.577335588+math.sin(q.anim_time*90*1-120)*-1", -4.61854, -1.91757]
|
||||
},
|
||||
"tail_right3_3": {
|
||||
"rotation": ["10+math.sin(q.anim_time*90*1-180)*-1", 0, 0]
|
||||
},
|
||||
"tail_right3_4": {
|
||||
"rotation": ["-30+math.sin(q.anim_time*90*1-240)*-4", 0, 0]
|
||||
},
|
||||
"tail_right3_5": {
|
||||
"rotation": ["-27.860824367+math.sin(q.anim_time*90*1-300)*-6", 8.86042, -4.65468]
|
||||
},
|
||||
"tail_right3_6": {
|
||||
"rotation": ["-43.1852829+math.sin(q.anim_time*90*1-300)*-6", -9.18229, 8.51814]
|
||||
},
|
||||
"tail_right3_7": {
|
||||
"rotation": ["35.413183453+math.sin(q.anim_time*90*1-360)*-12", -8.17773, -5.77509]
|
||||
},
|
||||
"tail_left4_rotation": {
|
||||
"rotation": ["-0+math.sin(q.anim_time*90*1-60)*-0.5", 10, 0]
|
||||
},
|
||||
"tail_left4_2": {
|
||||
"rotation": ["17.5+math.sin(q.anim_time*90*1-120)*-1", 0, 0]
|
||||
},
|
||||
"tail_left4_3": {
|
||||
"rotation": ["20.4458201+math.sin(q.anim_time*90*1-180)*-2", -11.73507, -4.3361]
|
||||
},
|
||||
"tail_left4_4": {
|
||||
"rotation": ["-41.341977449+math.sin(q.anim_time*90*1-240)*-4", -13.31791, 11.45696]
|
||||
},
|
||||
"tail_left4_5": {
|
||||
"rotation": ["-35.413183453+math.sin(q.anim_time*90*1-300)*-6", 8.17773, -5.77509]
|
||||
},
|
||||
"tail_left4_6": {
|
||||
"rotation": ["39.711284319+math.sin(q.anim_time*90*1-360)*-12", 17.67415, 14.15251]
|
||||
},
|
||||
"tail_right4_rotation": {
|
||||
"rotation": ["-0+math.sin(q.anim_time*90*1-60)*-0.5", -10, 0]
|
||||
},
|
||||
"tail_right4_2": {
|
||||
"rotation": ["17.5+math.sin(q.anim_time*90*1-120)*-1", 0, 0]
|
||||
},
|
||||
"tail_right4_3": {
|
||||
"rotation": ["20.4458201+math.sin(q.anim_time*90*1-180)*-2", 11.73507, 4.3361]
|
||||
},
|
||||
"tail_right4_4": {
|
||||
"rotation": ["-41.341977449+math.sin(q.anim_time*90*1-240)*-4", 13.31791, -11.45696]
|
||||
},
|
||||
"tail_right4_5": {
|
||||
"rotation": ["-35.413183453+math.sin(q.anim_time*90*1-300)*-6", -8.17773, 5.77509]
|
||||
},
|
||||
"tail_right4_6": {
|
||||
"rotation": ["39.711284319+math.sin(q.anim_time*90*1-360)*-12", -17.67415, -14.15251]
|
||||
},
|
||||
"neck_fur_front": {
|
||||
"rotation": ["-0+math.sin(q.anim_time*90*1-60)*-1", 0, 0]
|
||||
},
|
||||
"neck_fur_front2": {
|
||||
"rotation": ["-0+math.sin(q.anim_time*90*1-90)*2", 0, 0]
|
||||
},
|
||||
"neck_fur_front3": {
|
||||
"rotation": ["-0+math.sin(q.anim_time*90*1-120)*2", 0, 0]
|
||||
},
|
||||
"ear_left": {
|
||||
"rotation": ["-0+math.sin(q.anim_time*90*1-120)*1", 0, "0-math.sin(q.anim_time*90*1-30)*2"]
|
||||
},
|
||||
"ear_right": {
|
||||
"rotation": ["-0+math.sin(q.anim_time*90*1-120)*1", 0, "-0+math.sin(q.anim_time*90*1-30)*2"]
|
||||
},
|
||||
"hair": {
|
||||
"rotation": ["-0+math.sin(q.anim_time*90*1-150)*2", 0, 0]
|
||||
},
|
||||
"hair_detail": {
|
||||
"rotation": ["-0+math.sin(q.anim_time*90*1-180)*1", 0, 0]
|
||||
},
|
||||
"hair_detail2": {
|
||||
"rotation": ["-0+math.sin(q.anim_time*90*1-240)*1", 0, 0]
|
||||
},
|
||||
"hair_back_bottom": {
|
||||
"rotation": ["-0+math.sin(q.anim_time*90*1-320)*2", 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.ninetales.base": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"body": {
|
||||
@@ -276,64 +582,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.ninetales.cry": {
|
||||
"animation_length": 1,
|
||||
"bones": {
|
||||
"mouth": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.25": [0, -0.0999, -0.00436],
|
||||
"0.75": [0, -0.0999, -0.00436],
|
||||
"1.0": [0, 0, 0]
|
||||
}
|
||||
},
|
||||
"head": {
|
||||
"rotation": {
|
||||
"0.0": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.25": {
|
||||
"post": [-15, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.6667": {
|
||||
"post": [-15, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.9167": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
}
|
||||
}
|
||||
},
|
||||
"jaw": {
|
||||
"rotation": {
|
||||
"0.0": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.25": {
|
||||
"post": [65, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.75": {
|
||||
"post": [65, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.0": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"sound_effects": {
|
||||
"0.0": {
|
||||
"effect": "pokemon.ninetales.cry"
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.ninetales.blink": {
|
||||
"animation_length": 0.1667,
|
||||
"bones": {
|
||||
@@ -413,6 +661,164 @@
|
||||
"position": [-0.1, 0, -0.1]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.ninetales.cry": {
|
||||
"animation_length": 2,
|
||||
"bones": {
|
||||
"torso": {
|
||||
"rotation": {
|
||||
"0.0": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.25": {
|
||||
"post": [1, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.5": {
|
||||
"post": [-2, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.3333": {
|
||||
"post": [-4, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.6667": {
|
||||
"post": [-0.5, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"2.0": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
}
|
||||
}
|
||||
},
|
||||
"neck2": {
|
||||
"rotation": {
|
||||
"0.0": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.2083": {
|
||||
"post": [2.5, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.4167": {
|
||||
"post": [-5, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.25": {
|
||||
"post": [-7.5, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.625": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"2.0": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
}
|
||||
}
|
||||
},
|
||||
"head_rotation": {
|
||||
"rotation": {
|
||||
"0.0": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.2083": {
|
||||
"post": [5, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.4583": {
|
||||
"post": [-22.5, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.25": {
|
||||
"post": [-27, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.625": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"2.0": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
}
|
||||
}
|
||||
},
|
||||
"eyelid_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.3333": {"pre": [0, 0, 0], "post": [0.1, 0, -0.1]},
|
||||
"1.5": {"pre": [0.1, 0, -0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"eyelid_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.3333": {"pre": [0, 0, 0], "post": [-0.1, 0, -0.1]},
|
||||
"1.5": {"pre": [-0.1, 0, -0.1], "post": [0, 0, 0]}
|
||||
}
|
||||
},
|
||||
"jaw": {
|
||||
"rotation": {
|
||||
"0.2917": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.5": {
|
||||
"post": [47.5, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.25": {
|
||||
"post": [20, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.5417": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
}
|
||||
},
|
||||
"position": [0, 0, 0]
|
||||
},
|
||||
"hair": {
|
||||
"rotation": {
|
||||
"0.0": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.1667": {
|
||||
"post": [10, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.5": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.1667": {
|
||||
"post": [-2.5, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.625": {
|
||||
"post": [5, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"2.0": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"sound_effects": {
|
||||
"0.3333": {
|
||||
"effect": "pokemon.ninetales.cry"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+573
-53
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"format_version": "1.8.0",
|
||||
"animations": {
|
||||
"animation.ninetales_alolan.ground_idle": {
|
||||
"animation.ninetales_alolan.base": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"body": {
|
||||
@@ -381,61 +381,411 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.ninetales_alolan.cry": {
|
||||
"animation_length": 1,
|
||||
"animation.ninetales_alolan.ground_idle": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"mouth": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.25": [0, -0.0999, -0.00436],
|
||||
"0.75": [0, -0.0999, -0.00436],
|
||||
"1.0": [0, 0, 0]
|
||||
}
|
||||
"body": {
|
||||
"position": [0, -0.25, 0]
|
||||
},
|
||||
"head": {
|
||||
"rotation": {
|
||||
"0.0": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.25": {
|
||||
"post": [-15, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.6667": {
|
||||
"post": [-15, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.9167": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
}
|
||||
}
|
||||
"torso": {
|
||||
"rotation": ["2.5+math.sin(q.anim_time*90*1-0)*0.5", 0, "0-math.sin(q.anim_time*90*0.5-30)*0.5"]
|
||||
},
|
||||
"jaw": {
|
||||
"rotation": {
|
||||
"0.0": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.25": {
|
||||
"post": [65, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.75": {
|
||||
"post": [65, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.0": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"sound_effects": {
|
||||
"0.0": {
|
||||
"effect": "pokemon.ninetales_alolan.cry"
|
||||
"chest": {
|
||||
"rotation": ["-5+math.sin(q.anim_time*90*1-30)*0.5", 0, 0]
|
||||
},
|
||||
"neck": {
|
||||
"rotation": ["-10+math.sin(q.anim_time*90*1-60)*1", 0, 0]
|
||||
},
|
||||
"neck2": {
|
||||
"rotation": ["-10+math.sin(q.anim_time*90*1-90)*0.5", 0, 0]
|
||||
},
|
||||
"head_rotation": {
|
||||
"rotation": ["14.54701+math.sin(q.anim_time*90*1-90)*-2", -3.59452, "0.40543-math.sin(q.anim_time*90*1-120)*-0.5"]
|
||||
},
|
||||
"hair": {
|
||||
"rotation": ["13.75153+math.sin(q.anim_time*90*1-90)*1", 7.26228, 1.47729]
|
||||
},
|
||||
"hair2": {
|
||||
"rotation": ["-12.54624+math.sin(q.anim_time*90*1-120)*2", 4.88119, -1.08482]
|
||||
},
|
||||
"hair3": {
|
||||
"rotation": ["-24.58726+math.sin(q.anim_time*90*1-180)*2", -15.69466, 1.78427]
|
||||
},
|
||||
"hair4": {
|
||||
"rotation": ["3.48303+math.sin(q.anim_time*90*1-240)*4", -24.77164, -8.26511]
|
||||
},
|
||||
"hair5": {
|
||||
"rotation": ["-7.97337+math.sin(q.anim_time*90*1-300)*8", -59.03741, 4.53051]
|
||||
},
|
||||
"hair_bottom": {
|
||||
"rotation": ["7.5+math.sin(q.anim_time*90*1-360)*12", 0, 0]
|
||||
},
|
||||
"hair_bottom2": {
|
||||
"rotation": ["-27.70212+math.sin(q.anim_time*90*1-420)*18", -6.64851, 3.47875]
|
||||
},
|
||||
"hair_bottom3": {
|
||||
"rotation": ["25.56145+math.sin(q.anim_time*90*1-480)*24", -27.51235, -12.45891]
|
||||
},
|
||||
"hair6": {
|
||||
"rotation": ["7.5+math.sin(q.anim_time*90*1-360)*12", 0, 0]
|
||||
},
|
||||
"hair7": {
|
||||
"rotation": ["-40.98084+math.sin(q.anim_time*90*1-420)*18", -11.43563, 9.77243]
|
||||
},
|
||||
"hair8": {
|
||||
"rotation": ["30.86748+math.sin(q.anim_time*90*1-480)*24", -12.95254, -7.63074]
|
||||
},
|
||||
"tail": {
|
||||
"rotation": [0, 0, 0]
|
||||
},
|
||||
"tail_middle_rotation": {
|
||||
"rotation": ["65+math.sin(q.anim_time*90*1-60)*-0.5", 0, 0]
|
||||
},
|
||||
"tail_middle2": {
|
||||
"rotation": ["-7.5+math.sin(q.anim_time*90*1-120)*-1", 0, 0]
|
||||
},
|
||||
"tail_middle3": {
|
||||
"rotation": ["-25+math.sin(q.anim_time*90*1-180)*-2", 0, 0]
|
||||
},
|
||||
"tail_middle4": {
|
||||
"rotation": ["-30+math.sin(q.anim_time*90*1-240)*-4", 0, 0]
|
||||
},
|
||||
"tail_middle5": {
|
||||
"rotation": ["-25+math.sin(q.anim_time*90*1-300)*-6", 0, 0]
|
||||
},
|
||||
"tail_middle6": {
|
||||
"rotation": ["-12.62353+math.sin(q.anim_time*90*1-360)*-12", 7.24305, -1.95155]
|
||||
},
|
||||
"tail_middle7": {
|
||||
"rotation": ["-31.18939+math.sin(q.anim_time*90*1-400)*-12", -15.09492, 8.95891]
|
||||
},
|
||||
"tail_middle8": {
|
||||
"rotation": ["15.22074+math.sin(q.anim_time*90*1-460)*-12", 9.65594, 2.61298]
|
||||
},
|
||||
"tail_middle9": {
|
||||
"rotation": ["-20+math.sin(q.anim_time*90*1-520)*-18", 0, 0]
|
||||
},
|
||||
"tail_left1_rotation": {
|
||||
"rotation": ["64.2174+math.sin(q.anim_time*90*1-60)*-0.5", 8.98581, 12.04686]
|
||||
},
|
||||
"tail_left1_2": {
|
||||
"rotation": ["-17.51565+math.sin(q.anim_time*90*1-120)*-1", -2.38422, 0.7522]
|
||||
},
|
||||
"tail_left1_3": {
|
||||
"rotation": ["-10.03742+math.sin(q.anim_time*90*1-180)*-2", -4.92385, 0.87038]
|
||||
},
|
||||
"tail_left1_4": {
|
||||
"rotation": ["-37.52635+math.sin(q.anim_time*90*1-240)*-4", -1.98315, 1.52251]
|
||||
},
|
||||
"tail_left1_5": {
|
||||
"rotation": ["-17.51565+math.sin(q.anim_time*90*1-300)*-6", -2.38422, 0.7522]
|
||||
},
|
||||
"tail_left1_6": {
|
||||
"rotation": ["-25.08377+math.sin(q.anim_time*90*1-360)*-12", -4.53051, 2.11751]
|
||||
},
|
||||
"tail_left1_7": {
|
||||
"rotation": ["-15.22074+math.sin(q.anim_time*90*1-400)*-12", 9.65594, -2.61298]
|
||||
},
|
||||
"tail_left1_8": {
|
||||
"rotation": ["30.71983+math.sin(q.anim_time*90*1-460)*-12", -13.97399, -3.85625]
|
||||
},
|
||||
"tail_left1_9": {
|
||||
"rotation": ["-42.24682+math.sin(q.anim_time*90*1-520)*-18", 17.04679, -14.9092]
|
||||
},
|
||||
"tail_left2_rotation": {
|
||||
"rotation": ["63.58314+math.sin(q.anim_time*90*1-60)*-0.5", 11.98346, 41.65117]
|
||||
},
|
||||
"tail_left2_2": {
|
||||
"rotation": ["-15.50409+math.sin(q.anim_time*90*1-120)*-1", -14.47751, 3.96713]
|
||||
},
|
||||
"tail_left2_3": {
|
||||
"rotation": ["-9.9045+math.sin(q.anim_time*90*1-180)*-2", -2.61747, -1.08202]
|
||||
},
|
||||
"tail_left2_4": {
|
||||
"rotation": ["-27.5209+math.sin(q.anim_time*90*1-240)*-4", -2.26564, 1.0571]
|
||||
},
|
||||
"tail_left2_5": {
|
||||
"rotation": ["-30.09468+math.sin(q.anim_time*90*1-300)*-6", -4.32875, 2.50477]
|
||||
},
|
||||
"tail_left2_6": {
|
||||
"rotation": ["-13.06681+math.sin(q.anim_time*90*1-360)*-12", 11.06861, -5.84485]
|
||||
},
|
||||
"tail_left2_7": {
|
||||
"rotation": ["-25.08377+math.sin(q.anim_time*90*1-400)*-12", 4.53051, -2.11751]
|
||||
},
|
||||
"tail_left2_8": {
|
||||
"rotation": ["21.88023+math.sin(q.anim_time*90*1-460)*-12", -23.39896, -9.06159]
|
||||
},
|
||||
"tail_left2_9": {
|
||||
"rotation": ["-0+math.sin(q.anim_time*90*1-520)*-18", 25, 0]
|
||||
},
|
||||
"tail_left3": {
|
||||
"rotation": [-7.34619, 17.12827, -7.84022]
|
||||
},
|
||||
"tail_left3_rotation": {
|
||||
"rotation": ["76.5201+math.sin(q.anim_time*90*1-60)*-0.5", -21.21599, 70.91151]
|
||||
},
|
||||
"tail_left3_2": {
|
||||
"rotation": ["-23.00013+math.sin(q.anim_time*90*1-120)*-1", -11.40209, 5.14995]
|
||||
},
|
||||
"tail_left3_3": {
|
||||
"rotation": ["-10+math.sin(q.anim_time*90*1-180)*-2", 0, 0]
|
||||
},
|
||||
"tail_left3_4": {
|
||||
"rotation": ["-20+math.sin(q.anim_time*90*1-240)*-4", 0, 0]
|
||||
},
|
||||
"tail_left3_5": {
|
||||
"rotation": ["-30.02363+math.sin(q.anim_time*90*1-300)*-6", 2.16489, -1.2506]
|
||||
},
|
||||
"tail_left3_6": {
|
||||
"rotation": ["-12.99008+math.sin(q.anim_time*90*1-360)*-12", 11.53486, -4.8493]
|
||||
},
|
||||
"tail_left3_7": {
|
||||
"rotation": ["15+math.sin(q.anim_time*90*1-400)*-12", 20, 0]
|
||||
},
|
||||
"tail_left3_8": {
|
||||
"rotation": ["-22.89875+math.sin(q.anim_time*90*1-460)*-12", -8.42145, 5.41207]
|
||||
},
|
||||
"tail_left3_9": {
|
||||
"rotation": ["30+math.sin(q.anim_time*90*1-520)*-18", 22.5, 0]
|
||||
},
|
||||
"tail_left4_rotation": {
|
||||
"rotation": ["83.07626+math.sin(q.anim_time*90*1-60)*-0.5", 7.16729, 88.89799]
|
||||
},
|
||||
"tail_left4_2": {
|
||||
"rotation": ["-28.3693+math.sin(q.anim_time*90*1-120)*-1", -12.72029, 8.00075]
|
||||
},
|
||||
"tail_left4_3": {
|
||||
"rotation": ["-12.60443+math.sin(q.anim_time*90*1-180)*-2", -7.32123, 1.63219]
|
||||
},
|
||||
"tail_left4_4": {
|
||||
"rotation": ["-15.04624+math.sin(q.anim_time*90*1-240)*-4", -4.88119, 1.08482]
|
||||
},
|
||||
"tail_left4_5": {
|
||||
"rotation": ["-29.41237+math.sin(q.anim_time*90*1-300)*-6", -2.14804, -1.84068]
|
||||
},
|
||||
"tail_left4_6": {
|
||||
"rotation": ["-9.14867+math.sin(q.anim_time*90*1-360)*-12", 20.70481, -9.00717]
|
||||
},
|
||||
"tail_left4_7": {
|
||||
"rotation": ["-15+math.sin(q.anim_time*90*1-400)*-12", -2.5, 0]
|
||||
},
|
||||
"tail_left4_8": {
|
||||
"rotation": ["10+math.sin(q.anim_time*90*1-460)*-12", 20, 0]
|
||||
},
|
||||
"tail_left4_9": {
|
||||
"rotation": ["-0+math.sin(q.anim_time*90*1-520)*-18", -25, 0]
|
||||
},
|
||||
"tail_right1_rotation": {
|
||||
"rotation": ["64.2174+math.sin(q.anim_time*90*1-60)*-0.5", -8.98581, -12.04686]
|
||||
},
|
||||
"tail_right1_2": {
|
||||
"rotation": ["-17.51565+math.sin(q.anim_time*90*1-120)*-1", 2.38422, -0.7522]
|
||||
},
|
||||
"tail_right1_3": {
|
||||
"rotation": ["-10.03742+math.sin(q.anim_time*90*1-180)*-2", 4.92385, -0.87038]
|
||||
},
|
||||
"tail_right1_4": {
|
||||
"rotation": ["-37.52635+math.sin(q.anim_time*90*1-240)*-4", 1.98315, -1.52251]
|
||||
},
|
||||
"tail_right1_5": {
|
||||
"rotation": ["-17.51565+math.sin(q.anim_time*90*1-300)*-6", 2.38422, -0.7522]
|
||||
},
|
||||
"tail_right1_6": {
|
||||
"rotation": ["-25.08377+math.sin(q.anim_time*90*1-360)*-12", 4.53051, -2.11751]
|
||||
},
|
||||
"tail_right1_7": {
|
||||
"rotation": ["-15.22074+math.sin(q.anim_time*90*1-400)*-12", -9.65594, 2.61298]
|
||||
},
|
||||
"tail_right1_8": {
|
||||
"rotation": ["30.71983+math.sin(q.anim_time*90*1-460)*-12", 13.97399, 3.85625]
|
||||
},
|
||||
"tail_right1_9": {
|
||||
"rotation": ["-42.24682+math.sin(q.anim_time*90*1-520)*-18", -17.04679, 14.9092]
|
||||
},
|
||||
"tail_right2_rotation": {
|
||||
"rotation": ["63.58314+math.sin(q.anim_time*90*1-60)*-0.5", -11.98346, -41.65117]
|
||||
},
|
||||
"tail_right2_2": {
|
||||
"rotation": ["-15.50409+math.sin(q.anim_time*90*1-60)*-0.5", 14.47751, -3.96713]
|
||||
},
|
||||
"tail_right2_3": {
|
||||
"rotation": ["-9.9045+math.sin(q.anim_time*90*1-180)*-2", 2.61747, 1.08202]
|
||||
},
|
||||
"tail_right2_4": {
|
||||
"rotation": ["-27.5209+math.sin(q.anim_time*90*1-240)*-4", 2.26564, -1.0571]
|
||||
},
|
||||
"tail_right2_5": {
|
||||
"rotation": ["-30.09468+math.sin(q.anim_time*90*1-300)*-6", 4.32875, -2.50477]
|
||||
},
|
||||
"tail_right2_6": {
|
||||
"rotation": ["-13.06681+math.sin(q.anim_time*90*1-360)*-12", -11.06861, 5.84485]
|
||||
},
|
||||
"tail_right2_7": {
|
||||
"rotation": ["-25.08377+math.sin(q.anim_time*90*1-400)*-12", -4.53051, 2.11751]
|
||||
},
|
||||
"tail_right2_8": {
|
||||
"rotation": ["21.88023+math.sin(q.anim_time*90*1-460)*-12", 23.39896, 9.06159]
|
||||
},
|
||||
"tail_right2_9": {
|
||||
"rotation": ["-0+math.sin(q.anim_time*90*1-520)*-18", -25, 0]
|
||||
},
|
||||
"leg_front_left": {
|
||||
"rotation": ["-4.99527+math.sin(q.anim_time*90*1-0)*-1", 0.21782, 2.4905],
|
||||
"position": [0, "0-math.sin(q.anim_time*90*1-0)*0.025", "0-math.sin(q.anim_time*90*1-0)*-0.15"]
|
||||
},
|
||||
"leg_front_left2": {
|
||||
"rotation": ["-5+math.sin(q.anim_time*90*1-0)*0.5", 0, 0]
|
||||
},
|
||||
"foot_front_left": {
|
||||
"rotation": ["9.99067+math.sin(q.anim_time*90*1-0)*0.5", 0.43399, -2.46207]
|
||||
},
|
||||
"leg_back_left": {
|
||||
"rotation": ["12.5048+math.sin(q.anim_time*90*1-0)*1", 1.93726, -2.22807],
|
||||
"position": [0, "0-math.sin(q.anim_time*90*1-0)*0.2", "0-math.sin(q.anim_time*90*1-0)*0.25"]
|
||||
},
|
||||
"leg_back_left2": {
|
||||
"rotation": ["-5+math.sin(q.anim_time*90*1-0)*1", 0, 0]
|
||||
},
|
||||
"leg_back_left3": {
|
||||
"rotation": ["-2.49673+math.sin(q.anim_time*90*1-0)*-1", -0.12261, 0.03929]
|
||||
},
|
||||
"foot_back_left": {
|
||||
"rotation": ["-5.00899+math.sin(q.anim_time*90*1-0)*-1", -0.3507, 2.5603]
|
||||
},
|
||||
"leg_front_right": {
|
||||
"rotation": ["7.47178+math.sin(q.anim_time*90*1-0)*-1", 0.65182, -4.95744],
|
||||
"position": [0, "0-math.sin(q.anim_time*90*1-0)*0.025", "0-math.sin(q.anim_time*90*1-0)*-0.15"]
|
||||
},
|
||||
"leg_front_right2": {
|
||||
"rotation": ["-2.5+math.sin(q.anim_time*90*1-0)*0.5", 0, 0]
|
||||
},
|
||||
"foot_front_right": {
|
||||
"rotation": ["-5+math.sin(q.anim_time*90*1-0)*0.5", 0, 5]
|
||||
},
|
||||
"leg_back_right": {
|
||||
"rotation": ["-9.8369+math.sin(q.anim_time*90*1-0)*1", 5.47408, 1.12804],
|
||||
"position": [0, "0-math.sin(q.anim_time*90*1-0)*0.2", "0-math.sin(q.anim_time*90*1-0)*0.25"]
|
||||
},
|
||||
"leg_back_right2": {
|
||||
"rotation": ["5+math.sin(q.anim_time*90*1-0)*1", 0, 0]
|
||||
},
|
||||
"leg_back_right3": {
|
||||
"rotation": ["-0+math.sin(q.anim_time*90*1-0)*-1", 0, 0]
|
||||
},
|
||||
"foot_back_right": {
|
||||
"rotation": ["4.98247+math.sin(q.anim_time*90*1-0)*-1", 0.85481, -2.34941]
|
||||
},
|
||||
"tail_right3": {
|
||||
"rotation": [-7.34619, -17.12827, 7.84022]
|
||||
},
|
||||
"tail_right3_rotation": {
|
||||
"rotation": ["76.5201+math.sin(q.anim_time*90*1-60)*-0.5", 21.21599, -70.91151]
|
||||
},
|
||||
"tail_right3_2": {
|
||||
"rotation": ["-23.00013+math.sin(q.anim_time*90*1-120)*-1", 11.40209, -5.14995]
|
||||
},
|
||||
"tail_right3_3": {
|
||||
"rotation": ["-10+math.sin(q.anim_time*90*1-180)*-2", 0, 0]
|
||||
},
|
||||
"tail_right3_4": {
|
||||
"rotation": ["-20+math.sin(q.anim_time*90*1-240)*-4", 0, 0]
|
||||
},
|
||||
"tail_right3_5": {
|
||||
"rotation": ["-30.02363+math.sin(q.anim_time*90*1-300)*-6", -2.16489, 1.2506]
|
||||
},
|
||||
"tail_right3_6": {
|
||||
"rotation": ["-12.99008+math.sin(q.anim_time*90*1-360)*-12", -11.53486, 4.8493]
|
||||
},
|
||||
"tail_right3_7": {
|
||||
"rotation": ["15+math.sin(q.anim_time*90*1-400)*-12", -20, 0]
|
||||
},
|
||||
"tail_right3_8": {
|
||||
"rotation": ["-22.89875+math.sin(q.anim_time*90*1-460)*-12", 8.42145, -5.41207]
|
||||
},
|
||||
"tail_right3_9": {
|
||||
"rotation": ["30+math.sin(q.anim_time*90*1-520)*-18", -22.5, 0]
|
||||
},
|
||||
"tail_right4_rotation": {
|
||||
"rotation": ["83.07626+math.sin(q.anim_time*90*1-60)*-0.5", -7.16729, -88.89799]
|
||||
},
|
||||
"tail_right4_2": {
|
||||
"rotation": ["-28.3693+math.sin(q.anim_time*90*1-120)*-1", 12.72029, -8.00075]
|
||||
},
|
||||
"tail_right4_3": {
|
||||
"rotation": ["-12.60443+math.sin(q.anim_time*90*1-180)*-2", 7.32123, -1.63219]
|
||||
},
|
||||
"tail_right4_4": {
|
||||
"rotation": ["-15.04624+math.sin(q.anim_time*90*1-240)*-4", 4.88119, -1.08482]
|
||||
},
|
||||
"tail_right4_5": {
|
||||
"rotation": ["-29.41237+math.sin(q.anim_time*90*1-300)*-6", 2.14804, 1.84068]
|
||||
},
|
||||
"tail_right4_6": {
|
||||
"rotation": ["-9.14867+math.sin(q.anim_time*90*1-360)*-12", -20.70481, 9.00717]
|
||||
},
|
||||
"tail_right4_7": {
|
||||
"rotation": ["-15+math.sin(q.anim_time*90*1-400)*-12", 2.5, 0]
|
||||
},
|
||||
"tail_right4_8": {
|
||||
"rotation": ["10+math.sin(q.anim_time*90*1-460)*-12", -20, 0]
|
||||
},
|
||||
"tail_right4_9": {
|
||||
"rotation": ["-0+math.sin(q.anim_time*90*1-520)*-18", 25, 0]
|
||||
},
|
||||
"hair_left": {
|
||||
"rotation": [0, -17.5, "55+math.sin(q.anim_time*90*1-120)*2"]
|
||||
},
|
||||
"hair_left2": {
|
||||
"rotation": [-1.6575, 12.39135, "9.82005+math.sin(q.anim_time*90*1-180)*4"]
|
||||
},
|
||||
"hair_left3": {
|
||||
"rotation": [8.00384, 21.21629, "20.75164+math.sin(q.anim_time*90*1-240)*8"]
|
||||
},
|
||||
"hair_left4": {
|
||||
"rotation": [7.90373, -21.34916, "-15.85201+math.sin(q.anim_time*90*1-300)*18"]
|
||||
},
|
||||
"hair_left5": {
|
||||
"rotation": [-6.42784, -34.18333, "7.10385+math.sin(q.anim_time*90*1-360)*24"]
|
||||
},
|
||||
"hair_right": {
|
||||
"rotation": [0, 17.5, "-55-math.sin(q.anim_time*90*1-120)*2"]
|
||||
},
|
||||
"hair_right2": {
|
||||
"rotation": [-1.6575, -12.39135, "-9.82005-math.sin(q.anim_time*90*1-180)*4"]
|
||||
},
|
||||
"hair_right3": {
|
||||
"rotation": [8.00384, -21.21629, "-20.75164-math.sin(q.anim_time*90*1-240)*8"]
|
||||
},
|
||||
"hair_right4": {
|
||||
"rotation": [7.90373, 21.34916, "15.85201-math.sin(q.anim_time*90*1-300)*18"]
|
||||
},
|
||||
"hair_right5": {
|
||||
"rotation": [-6.42784, 34.18333, "-7.10385-math.sin(q.anim_time*90*1-360)*24"]
|
||||
},
|
||||
"neck_fur_front": {
|
||||
"rotation": ["-0+math.sin(q.anim_time*90*1-60)*-1", 0, 0]
|
||||
},
|
||||
"neck_fur_front2": {
|
||||
"rotation": ["-0+math.sin(q.anim_time*90*1-90)*2", 0, 0]
|
||||
},
|
||||
"neck_fur_front3": {
|
||||
"rotation": ["-0+math.sin(q.anim_time*90*1-120)*2", 0, 0]
|
||||
},
|
||||
"neck_fur_left": {
|
||||
"rotation": [0, 0, "0-math.sin(q.anim_time*90*1-90)*1"]
|
||||
},
|
||||
"neck_fur_right": {
|
||||
"rotation": [0, 0, "-0+math.sin(q.anim_time*90*1-90)*1"]
|
||||
},
|
||||
"ear_left": {
|
||||
"rotation": ["-0+math.sin(q.anim_time*90*1-120)*1", 0, "0-math.sin(q.anim_time*90*1-30)*2"]
|
||||
},
|
||||
"ear_right": {
|
||||
"rotation": ["-0+math.sin(q.anim_time*90*1-120)*1", 0, "-0+math.sin(q.anim_time*90*1-30)*2"]
|
||||
},
|
||||
"hair_front": {
|
||||
"rotation": ["-0+math.sin(q.anim_time*90*1-120)*2", 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -518,6 +868,176 @@
|
||||
"position": [-0.1, 0, -0.1]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.ninetales_alolan.cry": {
|
||||
"animation_length": 2,
|
||||
"bones": {
|
||||
"torso": {
|
||||
"rotation": {
|
||||
"0.0": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.25": {
|
||||
"post": [1, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.5": {
|
||||
"post": [-2, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.3333": {
|
||||
"post": [-4, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.6667": {
|
||||
"post": [-0.5, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"2.0": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
}
|
||||
}
|
||||
},
|
||||
"neck2": {
|
||||
"rotation": {
|
||||
"0.0": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.2083": {
|
||||
"post": [2.5, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.4167": {
|
||||
"post": [-5, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.25": {
|
||||
"post": [-7.5, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.625": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"2.0": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
}
|
||||
}
|
||||
},
|
||||
"head_rotation": {
|
||||
"rotation": {
|
||||
"0.0": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.2083": {
|
||||
"post": [5, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.4583": {
|
||||
"post": [-22.5, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.25": {
|
||||
"post": [-27, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.625": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"2.0": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
}
|
||||
}
|
||||
},
|
||||
"eyelid_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.3333": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0.1, 0, -0.1]
|
||||
},
|
||||
"1.5": {
|
||||
"pre": [0.1, 0, -0.1],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"eyelid_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.3333": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [-0.1, 0, -0.1]
|
||||
},
|
||||
"1.5": {
|
||||
"pre": [-0.1, 0, -0.1],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"jaw": {
|
||||
"rotation": {
|
||||
"0.2917": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.5": {
|
||||
"post": [47.5, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.25": {
|
||||
"post": [20, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.5417": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
}
|
||||
},
|
||||
"position": [0, 0, 0]
|
||||
},
|
||||
"hair": {
|
||||
"rotation": {
|
||||
"0.0": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.1667": {
|
||||
"post": [10, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.5": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.1667": {
|
||||
"post": [-2.5, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.625": {
|
||||
"post": [5, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"2.0": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"sound_effects": {
|
||||
"0.3333": {
|
||||
"effect": "pokemon.ninetales_alolan.cry"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+308
-74
@@ -1682,6 +1682,12 @@
|
||||
"1.3333": [10, 9, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"timeline": {
|
||||
"0.0": "q.run_molang('cobblemon:stepsound_standard_medium');",
|
||||
"0.4583": "q.run_molang('cobblemon:stepsound_standard_medium');",
|
||||
"0.6667": "q.run_molang('cobblemon:stepsound_standard_medium');",
|
||||
"1.125": "q.run_molang('cobblemon:stepsound_standard_medium');"
|
||||
}
|
||||
},
|
||||
"animation.arcanine.ride_ground_walk": {
|
||||
@@ -2639,6 +2645,12 @@
|
||||
"chest_fluff_right": {
|
||||
"rotation": [5, "-22.5+math.cos(q.anim_time*90*8-120)*15", "-math.sin(q.anim_time*90*8-120)*3"]
|
||||
}
|
||||
},
|
||||
"timeline": {
|
||||
"0.125": "q.run_molang('cobblemon:stepsound_standard_medium');",
|
||||
"0.2083": "q.run_molang('cobblemon:stepsound_standard_large');",
|
||||
"0.2917": "q.run_molang('cobblemon:stepsound_standard_medium');",
|
||||
"0.375": "q.run_molang('cobblemon:stepsound_standard_medium');"
|
||||
}
|
||||
},
|
||||
"animation.arcanine.ride_ground_run": {
|
||||
@@ -4161,41 +4173,101 @@
|
||||
"eye_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.1667": {"pre": [0, 0, 0], "post": [-0.1, 0, 0.1]},
|
||||
"0.5": {"pre": [-0.1, 0, 0.1], "post": [0, 0, 0]},
|
||||
"1.4167": {"pre": [0, 0, 0], "post": [-0.1, 0, 0.1]},
|
||||
"1.6667": {"pre": [-0.1, 0, 0.1], "post": [0, 0, 0]},
|
||||
"2.5": {"pre": [0, 0, 0], "post": [0, 0, 0]}
|
||||
"0.1667": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [-0.1, 0, 0.1]
|
||||
},
|
||||
"0.5": {
|
||||
"pre": [-0.1, 0, 0.1],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"1.4167": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [-0.1, 0, 0.1]
|
||||
},
|
||||
"1.6667": {
|
||||
"pre": [-0.1, 0, 0.1],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"2.5": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"eye_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.1667": {"pre": [0, 0, 0], "post": [0.1, 0, 0.1]},
|
||||
"0.5": {"pre": [0.1, 0, 0.1], "post": [0, 0, 0]},
|
||||
"1.4167": {"pre": [0, 0, 0], "post": [0.1, 0, 0.1]},
|
||||
"1.6667": {"pre": [0.1, 0, 0.1], "post": [0, 0, 0]},
|
||||
"2.5": {"pre": [0, 0, 0], "post": [0, 0, 0]}
|
||||
"0.1667": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0.1, 0, 0.1]
|
||||
},
|
||||
"0.5": {
|
||||
"pre": [0.1, 0, 0.1],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"1.4167": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0.1, 0, 0.1]
|
||||
},
|
||||
"1.6667": {
|
||||
"pre": [0.1, 0, 0.1],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"2.5": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"eyelid_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.1667": {"pre": [0, 0, 0], "post": [0.1, 0, -0.1]},
|
||||
"0.5": {"pre": [0.1, 0, -0.1], "post": [0, 0, 0]},
|
||||
"1.4167": {"pre": [0, 0, 0], "post": [0.1, 0, -0.1]},
|
||||
"1.6667": {"pre": [0.1, 0, -0.1], "post": [0, 0, 0]},
|
||||
"2.5": {"pre": [0, 0, 0], "post": [0, 0, 0]}
|
||||
"0.1667": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0.1, 0, -0.1]
|
||||
},
|
||||
"0.5": {
|
||||
"pre": [0.1, 0, -0.1],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"1.4167": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0.1, 0, -0.1]
|
||||
},
|
||||
"1.6667": {
|
||||
"pre": [0.1, 0, -0.1],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"2.5": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"eyelid_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.1667": {"pre": [0, 0, 0], "post": [-0.1, 0, -0.1]},
|
||||
"0.5": {"pre": [-0.1, 0, -0.1], "post": [0, 0, 0]},
|
||||
"1.4167": {"pre": [0, 0, 0], "post": [-0.1, 0, -0.1]},
|
||||
"1.6667": {"pre": [-0.1, 0, -0.1], "post": [0, 0, 0]},
|
||||
"2.5": {"pre": [0, 0, 0], "post": [0, 0, 0]}
|
||||
"0.1667": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [-0.1, 0, -0.1]
|
||||
},
|
||||
"0.5": {
|
||||
"pre": [-0.1, 0, -0.1],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"1.4167": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [-0.1, 0, -0.1]
|
||||
},
|
||||
"1.6667": {
|
||||
"pre": [-0.1, 0, -0.1],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"2.5": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"jaw": {
|
||||
@@ -4823,41 +4895,101 @@
|
||||
"eye_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.1667": {"pre": [0, 0, 0], "post": [-0.1, 0, 0.1]},
|
||||
"0.5": {"pre": [-0.1, 0, 0.1], "post": [0, 0, 0]},
|
||||
"1.4167": {"pre": [0, 0, 0], "post": [-0.1, 0, 0.1]},
|
||||
"1.6667": {"pre": [-0.1, 0, 0.1], "post": [0, 0, 0]},
|
||||
"2.5": {"pre": [0, 0, 0], "post": [0, 0, 0]}
|
||||
"0.1667": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [-0.1, 0, 0.1]
|
||||
},
|
||||
"0.5": {
|
||||
"pre": [-0.1, 0, 0.1],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"1.4167": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [-0.1, 0, 0.1]
|
||||
},
|
||||
"1.6667": {
|
||||
"pre": [-0.1, 0, 0.1],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"2.5": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"eye_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.1667": {"pre": [0, 0, 0], "post": [0.1, 0, 0.1]},
|
||||
"0.5": {"pre": [0.1, 0, 0.1], "post": [0, 0, 0]},
|
||||
"1.4167": {"pre": [0, 0, 0], "post": [0.1, 0, 0.1]},
|
||||
"1.6667": {"pre": [0.1, 0, 0.1], "post": [0, 0, 0]},
|
||||
"2.5": {"pre": [0, 0, 0], "post": [0, 0, 0]}
|
||||
"0.1667": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0.1, 0, 0.1]
|
||||
},
|
||||
"0.5": {
|
||||
"pre": [0.1, 0, 0.1],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"1.4167": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0.1, 0, 0.1]
|
||||
},
|
||||
"1.6667": {
|
||||
"pre": [0.1, 0, 0.1],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"2.5": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"eyelid_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.1667": {"pre": [0, 0, 0], "post": [0.1, 0, -0.1]},
|
||||
"0.5": {"pre": [0.1, 0, -0.1], "post": [0, 0, 0]},
|
||||
"1.4167": {"pre": [0, 0, 0], "post": [0.1, 0, -0.1]},
|
||||
"1.6667": {"pre": [0.1, 0, -0.1], "post": [0, 0, 0]},
|
||||
"2.5": {"pre": [0, 0, 0], "post": [0, 0, 0]}
|
||||
"0.1667": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0.1, 0, -0.1]
|
||||
},
|
||||
"0.5": {
|
||||
"pre": [0.1, 0, -0.1],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"1.4167": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0.1, 0, -0.1]
|
||||
},
|
||||
"1.6667": {
|
||||
"pre": [0.1, 0, -0.1],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"2.5": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"eyelid_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.1667": {"pre": [0, 0, 0], "post": [-0.1, 0, -0.1]},
|
||||
"0.5": {"pre": [-0.1, 0, -0.1], "post": [0, 0, 0]},
|
||||
"1.4167": {"pre": [0, 0, 0], "post": [-0.1, 0, -0.1]},
|
||||
"1.6667": {"pre": [-0.1, 0, -0.1], "post": [0, 0, 0]},
|
||||
"2.5": {"pre": [0, 0, 0], "post": [0, 0, 0]}
|
||||
"0.1667": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [-0.1, 0, -0.1]
|
||||
},
|
||||
"0.5": {
|
||||
"pre": [-0.1, 0, -0.1],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"1.4167": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [-0.1, 0, -0.1]
|
||||
},
|
||||
"1.6667": {
|
||||
"pre": [-0.1, 0, -0.1],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"2.5": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"jaw": {
|
||||
@@ -5287,14 +5419,20 @@
|
||||
"position": {
|
||||
"0.0": [-0.1, 0, 0.1],
|
||||
"0.125": [-0.1, 0, 0.1],
|
||||
"0.1667": {"pre": [-0.1, 0, 0.1], "post": [0, 0, 0]}
|
||||
"0.1667": {
|
||||
"pre": [-0.1, 0, 0.1],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"eye_right": {
|
||||
"position": {
|
||||
"0.0": [0.1, 0, 0.1],
|
||||
"0.125": [0.1, 0, 0.1],
|
||||
"0.1667": {"pre": [0.1, 0, 0.1], "post": [0, 0, 0]}
|
||||
"0.1667": {
|
||||
"pre": [0.1, 0, 0.1],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5491,47 +5629,95 @@
|
||||
"eye_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.0417": {"pre": [0, 0, 0], "post": [-0.2, 0, 0.1]},
|
||||
"0.3333": {"pre": [-0.2, 0, 0.1], "post": [0, 0, 0]},
|
||||
"1.25": {"pre": [0, 0, 0], "post": [0, 0, 0]}
|
||||
"0.0417": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [-0.2, 0, 0.1]
|
||||
},
|
||||
"0.3333": {
|
||||
"pre": [-0.2, 0, 0.1],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"1.25": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"eye_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.0417": {"pre": [0, 0, 0], "post": [0.2, 0, 0.1]},
|
||||
"0.3333": {"pre": [0.2, 0, 0.1], "post": [0, 0, 0]},
|
||||
"1.25": {"pre": [0, 0, 0], "post": [0, 0, 0]}
|
||||
"0.0417": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0.2, 0, 0.1]
|
||||
},
|
||||
"0.3333": {
|
||||
"pre": [0.2, 0, 0.1],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"1.25": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"eyelid_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.0417": {"pre": [0, 0, 0], "post": [-0.2, 0, 0.1]},
|
||||
"0.3333": {"pre": [-0.2, 0, 0.1], "post": [0, 0, 0]},
|
||||
"1.25": {"pre": [0, 0, 0], "post": [0, 0, 0]}
|
||||
"0.0417": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [-0.2, 0, 0.1]
|
||||
},
|
||||
"0.3333": {
|
||||
"pre": [-0.2, 0, 0.1],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"1.25": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"eyelid_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.0417": {"pre": [0, 0, 0], "post": [0.2, 0, 0.1]},
|
||||
"0.3333": {"pre": [0.2, 0, 0.1], "post": [0, 0, 0]},
|
||||
"1.25": {"pre": [0, 0, 0], "post": [0, 0, 0]}
|
||||
"0.0417": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0.2, 0, 0.1]
|
||||
},
|
||||
"0.3333": {
|
||||
"pre": [0.2, 0, 0.1],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"1.25": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"eyelid_left_hurt": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.0417": {"pre": [0, 0, 0], "post": [0.1, 0, -0.1]},
|
||||
"0.3333": {"pre": [0.1, 0, -0.1], "post": [0, 0, 0]}
|
||||
"0.0417": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0.1, 0, -0.1]
|
||||
},
|
||||
"0.3333": {
|
||||
"pre": [0.1, 0, -0.1],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"eyelid_right_hurt": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.0417": {"pre": [0, 0, 0], "post": [-0.1, 0, -0.1]},
|
||||
"0.3333": {"pre": [-0.1, 0, -0.1], "post": [0, 0, 0]}
|
||||
"0.0417": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [-0.1, 0, -0.1]
|
||||
},
|
||||
"0.3333": {
|
||||
"pre": [-0.1, 0, -0.1],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"jaw": {
|
||||
@@ -6238,47 +6424,95 @@
|
||||
"eye_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.0417": {"pre": [0, 0, 0], "post": [-0.2, 0, 0.1]},
|
||||
"0.3333": {"pre": [-0.2, 0, 0.1], "post": [0, 0, 0]},
|
||||
"1.25": {"pre": [0, 0, 0], "post": [0, 0, 0]}
|
||||
"0.0417": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [-0.2, 0, 0.1]
|
||||
},
|
||||
"0.3333": {
|
||||
"pre": [-0.2, 0, 0.1],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"1.25": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"eye_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.0417": {"pre": [0, 0, 0], "post": [0.2, 0, 0.1]},
|
||||
"0.3333": {"pre": [0.2, 0, 0.1], "post": [0, 0, 0]},
|
||||
"1.25": {"pre": [0, 0, 0], "post": [0, 0, 0]}
|
||||
"0.0417": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0.2, 0, 0.1]
|
||||
},
|
||||
"0.3333": {
|
||||
"pre": [0.2, 0, 0.1],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"1.25": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"eyelid_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.0417": {"pre": [0, 0, 0], "post": [-0.2, 0, 0.1]},
|
||||
"0.3333": {"pre": [-0.2, 0, 0.1], "post": [0, 0, 0]},
|
||||
"1.25": {"pre": [0, 0, 0], "post": [0, 0, 0]}
|
||||
"0.0417": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [-0.2, 0, 0.1]
|
||||
},
|
||||
"0.3333": {
|
||||
"pre": [-0.2, 0, 0.1],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"1.25": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"eyelid_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.0417": {"pre": [0, 0, 0], "post": [0.2, 0, 0.1]},
|
||||
"0.3333": {"pre": [0.2, 0, 0.1], "post": [0, 0, 0]},
|
||||
"1.25": {"pre": [0, 0, 0], "post": [0, 0, 0]}
|
||||
"0.0417": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0.2, 0, 0.1]
|
||||
},
|
||||
"0.3333": {
|
||||
"pre": [0.2, 0, 0.1],
|
||||
"post": [0, 0, 0]
|
||||
},
|
||||
"1.25": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"eyelid_left_hurt": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.0417": {"pre": [0, 0, 0], "post": [0.1, 0, -0.1]},
|
||||
"0.3333": {"pre": [0.1, 0, -0.1], "post": [0, 0, 0]}
|
||||
"0.0417": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0.1, 0, -0.1]
|
||||
},
|
||||
"0.3333": {
|
||||
"pre": [0.1, 0, -0.1],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"eyelid_right_hurt": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.0417": {"pre": [0, 0, 0], "post": [-0.1, 0, -0.1]},
|
||||
"0.3333": {"pre": [-0.1, 0, -0.1], "post": [0, 0, 0]}
|
||||
"0.0417": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [-0.1, 0, -0.1]
|
||||
},
|
||||
"0.3333": {
|
||||
"pre": [-0.1, 0, -0.1],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"jaw": {
|
||||
|
||||
+1299
-19
File diff suppressed because it is too large.
Load diff
+4557
-55
File diff suppressed because it is too large.
Load diff
+240
-16
@@ -3,58 +3,274 @@
|
||||
"animations": {
|
||||
"animation.mudkip.ground_idle": {
|
||||
"loop": true,
|
||||
"animation_length": 2,
|
||||
"bones": {
|
||||
"head": {
|
||||
"rotation": [2.5, 0, 0]
|
||||
"rotation": ["2.5+math.sin(q.anim_time*90*4-90)*1.5", "math.sin(q.anim_time*90*2-60)*1.5", "math.sin(q.anim_time*90*2-60)*1"]
|
||||
},
|
||||
"fin2": {
|
||||
"rotation": [2.5, 0, 0]
|
||||
"rotation": [2.5, 0, "0+math.sin(q.anim_time*90*2-150)*-3"]
|
||||
},
|
||||
"cheek_left2": {
|
||||
"rotation": [0, -7.5, 0]
|
||||
"rotation": [0, -7.5, "0+math.sin(q.anim_time*90*4-90)*1.5"]
|
||||
},
|
||||
"leg_front_left": {
|
||||
"rotation": [7.5, 5, 0]
|
||||
"rotation": ["5+math.sin(q.anim_time*90*4)*2", 5, 0],
|
||||
"position": [0, "-0.125+math.sin(q.anim_time*90*4)*-0.05", "0+math.sin(q.anim_time*90*4)*-0.07"]
|
||||
},
|
||||
"leg_front_left2": {
|
||||
"rotation": [-7.5, 0, 0]
|
||||
"rotation": ["-5+math.sin(q.anim_time*90*4)*-2", 0, 0]
|
||||
},
|
||||
"leg_front_right": {
|
||||
"rotation": [7.5, -5, 0]
|
||||
"rotation": ["5+math.sin(q.anim_time*90*4)*2", -5, 0],
|
||||
"position": [0, "-0.125+math.sin(q.anim_time*90*4)*-0.05", "0+math.sin(q.anim_time*90*4)*-0.07"]
|
||||
},
|
||||
"leg_front_right2": {
|
||||
"rotation": [-7.5, 0, 0]
|
||||
"rotation": ["-5+math.sin(q.anim_time*90*4)*-2", 0, 0]
|
||||
},
|
||||
"leg_back_left": {
|
||||
"rotation": [5, -5, 0]
|
||||
"rotation": ["-5+math.sin(q.anim_time*90*4)*-1", -5, 0],
|
||||
"position": [0, "-0.125+math.sin(q.anim_time*90*4)*-0.025", "0+math.sin(q.anim_time*90*4)*0.035"]
|
||||
},
|
||||
"leg_back_left2": {
|
||||
"rotation": [-5, 0, 0]
|
||||
"rotation": ["5+math.sin(q.anim_time*90*4)*1", 0, 0]
|
||||
},
|
||||
"leg_back_right": {
|
||||
"rotation": [5, 5, 0]
|
||||
"rotation": ["-5+math.sin(q.anim_time*90*4)*-1", 5, 0],
|
||||
"position": [0, "-0.125+math.sin(q.anim_time*90*4)*-0.025", "0+math.sin(q.anim_time*90*4)*0.035"]
|
||||
},
|
||||
"leg_back_right2": {
|
||||
"rotation": [-5, 0, 0]
|
||||
"rotation": ["5+math.sin(q.anim_time*90*4)*1", 0, 0]
|
||||
},
|
||||
"body": {
|
||||
"position": [0, -0.1, 0]
|
||||
},
|
||||
"tail": {
|
||||
"rotation": [5, 0, 0]
|
||||
"rotation": ["6+math.sin(q.anim_time*90*4)*1", "0+math.sin(q.anim_time*90*2-90)*-10", 0]
|
||||
},
|
||||
"fin": {
|
||||
"rotation": [2.5, 0, 0]
|
||||
"rotation": [2.5, 0, "0+math.sin(q.anim_time*90*2-90)*-4"]
|
||||
},
|
||||
"cheek_right2": {
|
||||
"rotation": [0, -7.5, 0]
|
||||
"rotation": [0, 7.5, "0+math.sin(q.anim_time*90*4-90)*-1.5"]
|
||||
},
|
||||
"torso": {
|
||||
"rotation": ["0+math.sin(q.anim_time*90*4)*0.75", "0+math.sin(q.anim_time*90*2-30)*0.5", 0],
|
||||
"position": [0, "0+math.sin(q.anim_time*90*4+30)*-0.05", 0]
|
||||
},
|
||||
"tail2": {
|
||||
"rotation": [0, "0+math.sin(q.anim_time*90*2-150)*-12.5", 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.mudkip.battle_idle": {
|
||||
"loop": true,
|
||||
"animation_length": 2,
|
||||
"bones": {
|
||||
"head": {
|
||||
"rotation": ["-7.5+math.sin(q.anim_time*90*4-90)*3", "math.sin(q.anim_time*90*2-60)*1", "math.sin(q.anim_time*90*2-60)*1"]
|
||||
},
|
||||
"fin2": {
|
||||
"rotation": [2.5, 0, "0+math.sin(q.anim_time*90*2-120)*-3"]
|
||||
},
|
||||
"cheek_left2": {
|
||||
"rotation": [0, -7.5, "-5+math.sin(q.anim_time*90*4-90)*1.5"]
|
||||
},
|
||||
"leg_front_left": {
|
||||
"rotation": ["4.305+math.sin(q.anim_time*90*4)*2", 5.60922, -7.50745],
|
||||
"position": [0, "-0.275+math.sin(q.anim_time*90*4)*-0.05", "0.3+math.sin(q.anim_time*90*4)*-0.07"]
|
||||
},
|
||||
"leg_front_left2": {
|
||||
"rotation": ["-4.9575+math.sin(q.anim_time*90*4)*-2", 0.65182, 7.47178]
|
||||
},
|
||||
"leg_front_right": {
|
||||
"rotation": ["4.305+math.sin(q.anim_time*90*4)*2", -5.60922, 7.50745],
|
||||
"position": [0, "-0.275+math.sin(q.anim_time*90*4)*-0.05", "0.3+math.sin(q.anim_time*90*4)*-0.07"]
|
||||
},
|
||||
"leg_front_right2": {
|
||||
"rotation": ["-4.9575+math.sin(q.anim_time*90*4)*-2", -0.65182, -7.47178]
|
||||
},
|
||||
"leg_back_left": {
|
||||
"rotation": ["-5+math.sin(q.anim_time*90*4)*-1", -5, 0],
|
||||
"position": [0, "-0.125+math.sin(q.anim_time*90*4)*-0.025", "0+math.sin(q.anim_time*90*4)*0.035"]
|
||||
},
|
||||
"leg_back_left2": {
|
||||
"rotation": ["5+math.sin(q.anim_time*90*4)*1", 0, 0]
|
||||
},
|
||||
"leg_back_right": {
|
||||
"rotation": ["-5+math.sin(q.anim_time*90*4)*-1", 5, 0],
|
||||
"position": [0, "-0.125+math.sin(q.anim_time*90*4)*-0.025", "0+math.sin(q.anim_time*90*4)*0.035"]
|
||||
},
|
||||
"leg_back_right2": {
|
||||
"rotation": ["5+math.sin(q.anim_time*90*4)*1", 0, 0]
|
||||
},
|
||||
"body": {
|
||||
"position": [0, -0.1, 0]
|
||||
},
|
||||
"tail": {
|
||||
"rotation": ["6+math.sin(q.anim_time*90*4)*1", "0+math.sin(q.anim_time*90*2-90)*-17.5", 0]
|
||||
},
|
||||
"fin": {
|
||||
"rotation": [2.5, 0, "0+math.sin(q.anim_time*90*2-90)*-4"]
|
||||
},
|
||||
"cheek_right2": {
|
||||
"rotation": [0, 7.5, "5+math.sin(q.anim_time*90*4-90)*-1.5"]
|
||||
},
|
||||
"torso": {
|
||||
"rotation": ["10+math.sin(q.anim_time*90*4)*2.5", "math.sin(q.anim_time*90*2-30)*0.5", 0],
|
||||
"position": [0, "0+math.sin(q.anim_time*90*4+30)*-0.07", 0]
|
||||
},
|
||||
"tail2": {
|
||||
"rotation": [0, "0+math.sin(q.anim_time*90*2-90)*-7.5", 0]
|
||||
},
|
||||
"eye_angry_left": {
|
||||
"position": [0, 0, -0.1]
|
||||
},
|
||||
"eye_angry_right": {
|
||||
"position": [0, 0, -0.1]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.mudkip.cry": {
|
||||
"animation_length": 1.2,
|
||||
"animation_length": 1.75,
|
||||
"bones": {
|
||||
"torso": {
|
||||
"rotation": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.2917": [5, 0, 0],
|
||||
"0.5": [0, 0, 0],
|
||||
"1.0": [-2.5, 0, 0],
|
||||
"1.5": [0, 0, 0]
|
||||
}
|
||||
},
|
||||
"head": {
|
||||
"rotation": {
|
||||
"0.0": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.2083": {
|
||||
"post": [10, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.375": {
|
||||
"post": [10, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.5833": {
|
||||
"post": [-10, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.7083": {
|
||||
"post": [-10, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.0833": {
|
||||
"post": [-17.5, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.2917": {
|
||||
"post": [-3, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.625": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
}
|
||||
}
|
||||
},
|
||||
"jaw": {
|
||||
"rotation": {
|
||||
"0.0": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.3333": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.625": {
|
||||
"post": [35, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.7083": {
|
||||
"post": [15, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.0": {
|
||||
"post": [60, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.0833": {
|
||||
"post": [60, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.3333": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
}
|
||||
}
|
||||
},
|
||||
"fin": {
|
||||
"rotation": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.25": [6, 0, 0],
|
||||
"1.0": [-5, 0, 0],
|
||||
"1.5": [0, 0, 0]
|
||||
}
|
||||
},
|
||||
"cheek_left2": {
|
||||
"rotation": {
|
||||
"0.375": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.75": {
|
||||
"post": [0, 0, -12.5],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.8333": {
|
||||
"post": [0, 0, -12.5],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.5": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
}
|
||||
}
|
||||
},
|
||||
"cheek_right2": {
|
||||
"rotation": {
|
||||
"0.375": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.75": {
|
||||
"post": [0, 0, 12.5],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.8333": {
|
||||
"post": [0, 0, 12.5],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.5": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
}
|
||||
}
|
||||
},
|
||||
"tail": {
|
||||
"rotation": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.625": [0, "0+math.sin(q.anim_time*90*12-90)*-25", 0],
|
||||
"1.625": [0, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"sound_effects": {
|
||||
"0.04": {
|
||||
"0.5417": {
|
||||
"effect": "pokemon.mudkip.cry"
|
||||
}
|
||||
}
|
||||
@@ -207,6 +423,14 @@
|
||||
"position": [-0.1, 0, -0.1]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.mudkip.WALKSPEED_TEST": {
|
||||
"loop": true,
|
||||
"bones": {
|
||||
"body": {
|
||||
"position": [0, 0, "q.anim_time*90*-0.07"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+221
-29
@@ -3,83 +3,173 @@
|
||||
"animations": {
|
||||
"animation.marshtomp.ground_idle": {
|
||||
"loop": true,
|
||||
"animation_length": 4,
|
||||
"bones": {
|
||||
"torso": {
|
||||
"rotation": [0, 0, 0]
|
||||
"rotation": ["0+math.sin(q.anim_time*90*4)*-1", "math.sin(q.anim_time*90*2)*2", "math.sin(q.anim_time*90*2)*-1"],
|
||||
"position": [0, "math.sin(q.anim_time*90*4-30)*-0.05", 0]
|
||||
},
|
||||
"chest": {
|
||||
"rotation": [-2.5, 0, 0]
|
||||
"rotation": ["0+math.sin(q.anim_time*90*4-30)*-1", "math.sin(q.anim_time*90*2-30)*1", "math.sin(q.anim_time*90*2-30)*-0.5"]
|
||||
},
|
||||
"neck": {
|
||||
"rotation": ["0+math.sin(q.anim_time*90*4-30)*2.5", 0, 0]
|
||||
},
|
||||
"head": {
|
||||
"rotation": [5, 0, 0]
|
||||
"rotation": ["5+math.sin(q.anim_time*90*4-30)*-3", "math.sin(q.anim_time*90*2-30)*1", "math.sin(q.anim_time*90*2-30)*-1.5"]
|
||||
},
|
||||
"head_fin": {
|
||||
"rotation": ["0+math.sin(q.anim_time*90*4-30)*-1.5", 0, 0]
|
||||
},
|
||||
"arm_left": {
|
||||
"rotation": [7.5, 0, 27.5]
|
||||
"rotation": [7.5, 0, "37.5+math.sin(q.anim_time*90*2)*-5"]
|
||||
},
|
||||
"arm_left2": {
|
||||
"rotation": [0, 15, 2.5]
|
||||
"rotation": [0, "15+math.sin(q.anim_time*90*2-30)*5", "2.5+math.sin(q.anim_time*90*2-60)*-5"]
|
||||
},
|
||||
"hand_left": {
|
||||
"rotation": [0, 0, 5]
|
||||
"rotation": [0, "0+math.sin(q.anim_time*90*2-120)*3", "10+math.sin(q.anim_time*90*2-150)*-2.5"]
|
||||
},
|
||||
"finger_front_left": {
|
||||
"rotation": [0, 2.5, 15]
|
||||
"rotation": [0, 0, "10+math.sin(q.anim_time*90*2-60)*-5"]
|
||||
},
|
||||
"finger_middle_left": {
|
||||
"rotation": [0, 0, 10]
|
||||
"rotation": [0, 0, "10+math.sin(q.anim_time*90*2-120)*-5"]
|
||||
},
|
||||
"finger_back_left": {
|
||||
"rotation": [0, -5, 20]
|
||||
"rotation": [0, 0, "10+math.sin(q.anim_time*90*2-180)*-5"]
|
||||
},
|
||||
"arm_right": {
|
||||
"rotation": [7.5, 0, -27.5]
|
||||
"rotation": [7.5, 0, "-37.5+math.sin(q.anim_time*90*2)*-5"]
|
||||
},
|
||||
"arm_right2": {
|
||||
"rotation": [0, -15, -2.5]
|
||||
"rotation": [0, "-15+math.sin(q.anim_time*90*2-30)*5", "-2.5+math.sin(q.anim_time*90*2-60)*-5"]
|
||||
},
|
||||
"hand_right": {
|
||||
"rotation": [0, 0, -5]
|
||||
"rotation": [0, "0+math.sin(q.anim_time*90*2-120)*3", "-10+math.sin(q.anim_time*90*2-150)*-2.5"]
|
||||
},
|
||||
"finger_front_right": {
|
||||
"rotation": [0, -2.5, -15]
|
||||
"rotation": [0, 0, "-10+math.sin(q.anim_time*90*2-60)*-5"]
|
||||
},
|
||||
"finger_middle_right": {
|
||||
"rotation": [0, 0, -10]
|
||||
"rotation": [0, 0, "-10+math.sin(q.anim_time*90*2-120)*-5"]
|
||||
},
|
||||
"finger_back_right": {
|
||||
"rotation": [0, 5, -20]
|
||||
"rotation": [0, 0, "-10+math.sin(q.anim_time*90*2-180)*-5"]
|
||||
},
|
||||
"tail_fin_left": {
|
||||
"rotation": [-5, 45, 0]
|
||||
"rotation": [-5, "45+math.sin(q.anim_time*90*2)*-12", 0]
|
||||
},
|
||||
"tail_fin_right": {
|
||||
"rotation": [-5, -45, 0]
|
||||
"rotation": [-5, "-45+math.sin(q.anim_time*90*2)*12", 0]
|
||||
},
|
||||
"leg_left": {
|
||||
"rotation": [2.5, 0, -2.5]
|
||||
"rotation": ["-2.5+math.sin(q.anim_time*90*2)*2.5", 0, 0],
|
||||
"position": [0, "-0.05+math.sin(q.anim_time*90*2)*0.1", "0+math.sin(q.anim_time*90*2)*-0.1"]
|
||||
},
|
||||
"leg_left2": {
|
||||
"rotation": ["2.5+math.sin(q.anim_time*90*2)*-2.5", 0, 0]
|
||||
},
|
||||
"leg_right": {
|
||||
"rotation": ["-2.5+math.sin(q.anim_time*90*2)*-2.5", 0, 0],
|
||||
"position": [0, "-0.05+math.sin(q.anim_time*90*2)*-0.1", "0+math.sin(q.anim_time*90*2)*0.1"]
|
||||
},
|
||||
"leg_right2": {
|
||||
"rotation": ["2.5+math.sin(q.anim_time*90*2)*2.5", 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.marshtomp.battle_idle": {
|
||||
"loop": true,
|
||||
"animation_length": 4,
|
||||
"bones": {
|
||||
"torso": {
|
||||
"rotation": ["0+math.sin(q.anim_time*90*4)*-2", "math.sin(q.anim_time*90*2)*4", "math.sin(q.anim_time*90*2)*-2"],
|
||||
"position": [0, "math.sin(q.anim_time*90*4)*0.05", 0]
|
||||
},
|
||||
"chest": {
|
||||
"rotation": ["-2.5+math.sin(q.anim_time*90*4-30)*-1", "math.sin(q.anim_time*90*2-30)*4", "math.sin(q.anim_time*90*2-30)*-2.5"]
|
||||
},
|
||||
"head": {
|
||||
"rotation": ["5+math.sin(q.anim_time*90*4-30)*-3", "math.sin(q.anim_time*90*2-30)*-6", "math.sin(q.anim_time*90*2-30)*5"]
|
||||
},
|
||||
"arm_left": {
|
||||
"rotation": [7.5, 0, "27.5+math.sin(q.anim_time*90*2)*-7.5"]
|
||||
},
|
||||
"arm_left2": {
|
||||
"rotation": [0, "15+math.sin(q.anim_time*90*2-30)*5", "2.5+math.sin(q.anim_time*90*2-30)*-5"]
|
||||
},
|
||||
"hand_left": {
|
||||
"rotation": [0, "0+math.sin(q.anim_time*90*2-90)*5", "5+math.sin(q.anim_time*90*2-90)*-7.5"]
|
||||
},
|
||||
"finger_front_left": {
|
||||
"rotation": [0, 2.5, "15+math.sin(q.anim_time*90*2-120)*-10"]
|
||||
},
|
||||
"finger_middle_left": {
|
||||
"rotation": [0, 0, "10+math.sin(q.anim_time*90*2-150)*-10"]
|
||||
},
|
||||
"finger_back_left": {
|
||||
"rotation": [0, -5, "20+math.sin(q.anim_time*90*2-180)*-10"]
|
||||
},
|
||||
"arm_right": {
|
||||
"rotation": [7.5, 0, "-27.5+math.sin(q.anim_time*90*2)*-7.5"]
|
||||
},
|
||||
"arm_right2": {
|
||||
"rotation": [0, "-15+math.sin(q.anim_time*90*2-30)*5", "-2.5+math.sin(q.anim_time*90*2-30)*-5"]
|
||||
},
|
||||
"hand_right": {
|
||||
"rotation": [0, "0+math.sin(q.anim_time*90*2-90)*5", "-5+math.sin(q.anim_time*90*2-90)*-7.5"]
|
||||
},
|
||||
"finger_front_right": {
|
||||
"rotation": [0, -2.5, "-15+math.sin(q.anim_time*90*2-120)*-10"]
|
||||
},
|
||||
"finger_middle_right": {
|
||||
"rotation": [0, 0, "-10+math.sin(q.anim_time*90*2-150)*-10"]
|
||||
},
|
||||
"finger_back_right": {
|
||||
"rotation": [0, 5, "-20+math.sin(q.anim_time*90*2-180)*-10"]
|
||||
},
|
||||
"tail_fin_left": {
|
||||
"rotation": [-5, "45+math.sin(q.anim_time*90*2)*-12", 0]
|
||||
},
|
||||
"tail_fin_right": {
|
||||
"rotation": [-5, "-45+math.sin(q.anim_time*90*2)*12", 0]
|
||||
},
|
||||
"leg_left": {
|
||||
"rotation": [2.4905, "0.2178+math.sin(q.anim_time*90*2)*1.5", -2.49527]
|
||||
},
|
||||
"leg_left2": {
|
||||
"rotation": [5, 0, 0]
|
||||
},
|
||||
"foot_left": {
|
||||
"rotation": [-7.5, 0, 2.5]
|
||||
"rotation": [-7.47178, "0.6518+math.sin(q.anim_time*90*2)*-1.5", 2.45744]
|
||||
},
|
||||
"leg_right": {
|
||||
"rotation": [2.5, 0, 2.5]
|
||||
"rotation": [2.4905, "-0.2178+math.sin(q.anim_time*90*2)*1.5", 2.49527]
|
||||
},
|
||||
"leg_right2": {
|
||||
"rotation": [5, 0, 0]
|
||||
},
|
||||
"foot_right": {
|
||||
"rotation": [-7.5, 0, -2.5]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.marshtomp.cry": {
|
||||
"animation_length": 1.2,
|
||||
"sound_effects": {
|
||||
"0.04": {
|
||||
"effect": "pokemon.marshtomp.cry"
|
||||
"rotation": [-7.47178, "-0.6518+math.sin(q.anim_time*90*2)*-1.5", -2.45744]
|
||||
},
|
||||
"body": {
|
||||
"position": [0, -0.15, 0]
|
||||
},
|
||||
"neck": {
|
||||
"rotation": ["0+math.sin(q.anim_time*90*4-30)*2.5", 0, 0]
|
||||
},
|
||||
"head_fin": {
|
||||
"rotation": ["0+math.sin(q.anim_time*90*4-30)*-1.5", 0, 0]
|
||||
},
|
||||
"eye_angry_left": {
|
||||
"position": [0, 0, -0.1]
|
||||
},
|
||||
"eye_angry_right": {
|
||||
"position": [0, 0, -0.1]
|
||||
},
|
||||
"jaw": {
|
||||
"rotation": ["5+math.sin(q.anim_time*90*4-30)*-5", 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -162,6 +252,108 @@
|
||||
"position": [0, 0, -0.1]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.marshtomp.cry": {
|
||||
"animation_length": 2,
|
||||
"bones": {
|
||||
"chest": {
|
||||
"rotation": {
|
||||
"0.0": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.125": {
|
||||
"post": [5, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.5": {
|
||||
"post": [-2.5, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.7917": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.0833": {
|
||||
"post": [-2.5, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.5833": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
}
|
||||
}
|
||||
},
|
||||
"head": {
|
||||
"rotation": {
|
||||
"0.0": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.125": {
|
||||
"post": [7.5, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.4167": {
|
||||
"post": [-12.5, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.625": {
|
||||
"post": [-5, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.8333": {
|
||||
"post": [-12.5, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.0417": {
|
||||
"post": [-12.5, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.4583": {
|
||||
"post": [-1.53, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.7083": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
}
|
||||
}
|
||||
},
|
||||
"jaw": {
|
||||
"rotation": {
|
||||
"0.0": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.2083": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.5": {
|
||||
"post": [27.5, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.75": {
|
||||
"post": [17.5, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.0833": {
|
||||
"post": [40, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.4583": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"sound_effects": {
|
||||
"0.4167": {
|
||||
"effect": "pokemon.marshtomp.cry"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+349
-34
@@ -3,30 +3,33 @@
|
||||
"animations": {
|
||||
"animation.swampert.ground_idle": {
|
||||
"loop": true,
|
||||
"animation_length": 4,
|
||||
"bones": {
|
||||
"body": {
|
||||
"position": [0, 1.75, 0]
|
||||
},
|
||||
"chest2": {
|
||||
"rotation": [-12.5, 0, 0]
|
||||
"rotation": ["-12.5+math.sin(q.anim_time*90*2-60)*0.75", 0, 0]
|
||||
},
|
||||
"neck": {
|
||||
"rotation": [-5, 0, 0]
|
||||
"rotation": ["-5+math.sin(q.anim_time*90*2-90)*1", "0+math.sin(q.anim_time*90*1-90)*-1", 0]
|
||||
},
|
||||
"leg_left": {
|
||||
"rotation": [8.77647, -12.0131, -53.28718]
|
||||
"rotation": ["8.7765+math.sin(q.anim_time*90*2)*-1.5", -12.0131, -53.28718],
|
||||
"position": [0, "0+math.sin(q.anim_time*90*2)*-0.1", "0+math.sin(q.anim_time*90*2)*0.15"]
|
||||
},
|
||||
"leg_left2": {
|
||||
"rotation": [4.54163, -0.2127, 45.09046]
|
||||
"rotation": [4.5416, -0.2127, 45.09046]
|
||||
},
|
||||
"leg_left3": {
|
||||
"rotation": [9.83802, -2.51058, 9.95791]
|
||||
},
|
||||
"foot_left": {
|
||||
"rotation": [-27.58324, -3.55523, 20.16242]
|
||||
"rotation": [-27.58324, "-3.5552+math.sin(q.anim_time*90*2)*-1.5", 20.16242]
|
||||
},
|
||||
"leg_right": {
|
||||
"rotation": [8.77647, 12.0131, 53.2872]
|
||||
"rotation": ["8.7765+math.sin(q.anim_time*90*2)*-1.5", 12.0131, 53.2872],
|
||||
"position": [0, "0+math.sin(q.anim_time*90*2)*-0.1", "0+math.sin(q.anim_time*90*2)*0.15"]
|
||||
},
|
||||
"leg_right2": {
|
||||
"rotation": [4.54163, 0.2127, -45.0905]
|
||||
@@ -35,16 +38,155 @@
|
||||
"rotation": [9.83802, 2.5106, -9.9579]
|
||||
},
|
||||
"foot_right": {
|
||||
"rotation": [-27.58324, 3.5552, -20.1624]
|
||||
"rotation": [-27.58324, "3.5552+math.sin(q.anim_time*90*2)*1.5", -20.1624]
|
||||
},
|
||||
"arm_left2": {
|
||||
"rotation": [-4.36302, -31.26463, 17.62528]
|
||||
"rotation": [-4.36302, -31.26463, "17.6253+math.sin(q.anim_time*90*2-90)*2"]
|
||||
},
|
||||
"arm_left3": {
|
||||
"rotation": [1.80384, 2.38704, 35.42915]
|
||||
"rotation": [1.80384, 2.38704, "35.4291+math.sin(q.anim_time*90*2-120)*2.5"]
|
||||
},
|
||||
"arm_left": {
|
||||
"rotation": [-13.31914, -14.63639, 12.92638]
|
||||
"rotation": [-13.31914, "-14.6364+math.sin(q.anim_time*90*2-60)*2", 12.92638]
|
||||
},
|
||||
"finger_front_left": {
|
||||
"rotation": [0, "-37.5+math.sin(q.anim_time*90*2-120)*-2.5", 20]
|
||||
},
|
||||
"finger_middle_left": {
|
||||
"rotation": [0, "-32.5+math.sin(q.anim_time*90*2-120)*-2.5", 0]
|
||||
},
|
||||
"finger_back_left": {
|
||||
"rotation": [0, "-30+math.sin(q.anim_time*90*2-120)*-2.5", -27.5]
|
||||
},
|
||||
"fingers_left": {
|
||||
"rotation": [0, 37.5, 0]
|
||||
},
|
||||
"arm_right": {
|
||||
"rotation": [-13.31914, "14.6364+math.sin(q.anim_time*90*2-60)*-2", -12.9264]
|
||||
},
|
||||
"arm_right2": {
|
||||
"rotation": [-4.33052, "31.2647+math.sin(q.anim_time*90*2-90)*2", -17.60892]
|
||||
},
|
||||
"arm_right3": {
|
||||
"rotation": [1.80384, -2.387, "-35.4292+math.sin(q.anim_time*90*2-120)*-2.5"]
|
||||
},
|
||||
"fingers_right": {
|
||||
"rotation": [0, -37.5, 0]
|
||||
},
|
||||
"finger_front_right": {
|
||||
"rotation": [0, "37.5+math.sin(q.anim_time*90*2-120)*2.5", -20]
|
||||
},
|
||||
"finger_middle_right": {
|
||||
"rotation": [0, "32.5+math.sin(q.anim_time*90*2-120)*2.5", 0]
|
||||
},
|
||||
"finger_back_right": {
|
||||
"rotation": [0, "30+math.sin(q.anim_time*90*2-120)*2.5", 27.5]
|
||||
},
|
||||
"torso": {
|
||||
"rotation": ["-5+math.sin(q.anim_time*90*2)*0.5", 0, 0],
|
||||
"position": [0, "0+math.sin(q.anim_time*90*2+30)*-0.4", 0]
|
||||
},
|
||||
"chest": {
|
||||
"rotation": ["-7.5+math.sin(q.anim_time*90*2-30)*1.5", 0, 0]
|
||||
},
|
||||
"hand_left": {
|
||||
"rotation": [0, "-17.5+math.sin(q.anim_time*90*2-90)*-5", 0]
|
||||
},
|
||||
"finger_front_left2": {
|
||||
"rotation": [0, "-12.5+math.sin(q.anim_time*90*2-150)*-5", 0]
|
||||
},
|
||||
"finger_middle_left2": {
|
||||
"rotation": [0, "-10+math.sin(q.anim_time*90*2-150)*-5", 0]
|
||||
},
|
||||
"finger_back_left2": {
|
||||
"rotation": [0, "-15+math.sin(q.anim_time*90*2-150)*-5", 0]
|
||||
},
|
||||
"hand_right": {
|
||||
"rotation": [0, "17.5+math.sin(q.anim_time*90*2-90)*5", 0]
|
||||
},
|
||||
"finger_front_right2": {
|
||||
"rotation": [0, "12.5+math.sin(q.anim_time*90*2-150)*5", 0]
|
||||
},
|
||||
"finger_middle_right2": {
|
||||
"rotation": [0, "10+math.sin(q.anim_time*90*2-150)*5", 0]
|
||||
},
|
||||
"finger_back_right2": {
|
||||
"rotation": [0, "15+math.sin(q.anim_time*90*2-150)*5", 0]
|
||||
},
|
||||
"check_left_spike_front": {
|
||||
"rotation": [0, "0+math.sin(q.anim_time*90*2-30)*3", 0]
|
||||
},
|
||||
"check_left_spike_back": {
|
||||
"rotation": [0, "0+math.sin(q.anim_time*90*2-30)*3", 0]
|
||||
},
|
||||
"check_right_spike_front": {
|
||||
"rotation": [0, "0+math.sin(q.anim_time*90*2-30)*-3", 0]
|
||||
},
|
||||
"check_right_spike_back": {
|
||||
"rotation": [0, "0+math.sin(q.anim_time*90*2-30)*-3", 0]
|
||||
},
|
||||
"eyebrow_left": {
|
||||
"rotation": [0, "-2.5+math.sin(q.anim_time*90*2-60)*-2.5", 0]
|
||||
},
|
||||
"eyebrow_right": {
|
||||
"rotation": [0, "2.5-math.sin(q.anim_time*90*2-60)*-2.5", 0]
|
||||
},
|
||||
"tail": {
|
||||
"rotation": ["0+math.sin(q.anim_time*90*2-30)*-2.5", 0, 0]
|
||||
},
|
||||
"head": {
|
||||
"rotation": ["12.5+math.sin(q.anim_time*90*2-90)*-2.5", "-0+math.sin(q.anim_time*90*1-90)*-0.5", 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.swampert.battle_idle": {
|
||||
"loop": true,
|
||||
"animation_length": 4,
|
||||
"bones": {
|
||||
"body": {
|
||||
"position": [0, 1.75, 0]
|
||||
},
|
||||
"chest2": {
|
||||
"rotation": ["-12.5+math.sin(q.anim_time*90*2-60)*0.75", 0, 0]
|
||||
},
|
||||
"neck": {
|
||||
"rotation": ["-5+math.sin(q.anim_time*90*2-90)*1", "0+math.sin(q.anim_time*90*1-90)*-1", 0]
|
||||
},
|
||||
"leg_left": {
|
||||
"rotation": ["8.7765+math.sin(q.anim_time*90*2)*-1.5", -12.0131, -53.28718],
|
||||
"position": [0, "0+math.sin(q.anim_time*90*2)*-0.1", "0+math.sin(q.anim_time*90*2)*0.15"]
|
||||
},
|
||||
"leg_left2": {
|
||||
"rotation": [4.5416, -0.2127, 45.09046]
|
||||
},
|
||||
"leg_left3": {
|
||||
"rotation": [9.83802, -2.51058, 9.95791]
|
||||
},
|
||||
"foot_left": {
|
||||
"rotation": [-27.58324, "-3.5552+math.sin(q.anim_time*90*2)*-1.5", 20.16242]
|
||||
},
|
||||
"leg_right": {
|
||||
"rotation": ["8.7765+math.sin(q.anim_time*90*2)*-1.5", 12.0131, 53.2872],
|
||||
"position": [0, "0+math.sin(q.anim_time*90*2)*-0.1", "0+math.sin(q.anim_time*90*2)*0.15"]
|
||||
},
|
||||
"leg_right2": {
|
||||
"rotation": [4.54163, 0.2127, -45.0905]
|
||||
},
|
||||
"leg_right3": {
|
||||
"rotation": [9.83802, 2.5106, -9.9579]
|
||||
},
|
||||
"foot_right": {
|
||||
"rotation": [-27.58324, "3.5552+math.sin(q.anim_time*90*2)*1.5", -20.1624]
|
||||
},
|
||||
"arm_left2": {
|
||||
"rotation": [-4.71002, "-12.8789-math.sin(q.anim_time*90*2-90)*2", 28.88472]
|
||||
},
|
||||
"arm_left3": {
|
||||
"rotation": [1.81234, "10.1983-math.sin(q.anim_time*90*2-30)*-5", 25.6704]
|
||||
},
|
||||
"arm_left": {
|
||||
"rotation": [-33.31914, "-14.6364-math.sin(q.anim_time*90*2-60)*-2", 12.9264],
|
||||
"position": [0, "0-math.sin(q.anim_time*90*2-30)*-0.3", 0]
|
||||
},
|
||||
"finger_front_left": {
|
||||
"rotation": [0, -37.5, 20]
|
||||
@@ -59,13 +201,14 @@
|
||||
"rotation": [0, 37.5, 0]
|
||||
},
|
||||
"arm_right": {
|
||||
"rotation": [-13.31914, 14.6364, -12.9264]
|
||||
"rotation": [-33.31914, "14.6364+math.sin(q.anim_time*90*2-60)*-2", -12.9264],
|
||||
"position": [0, "0-math.sin(q.anim_time*90*2-30)*-0.3", 0]
|
||||
},
|
||||
"arm_right2": {
|
||||
"rotation": [-4.36302, 31.2646, -17.6253]
|
||||
"rotation": [-4.71002, "12.8789+math.sin(q.anim_time*90*2-90)*2", -28.88472]
|
||||
},
|
||||
"arm_right3": {
|
||||
"rotation": [1.80384, -2.387, -35.4292]
|
||||
"rotation": [1.81234, "-10.1983+math.sin(q.anim_time*90*2-30)*-5", -25.6704]
|
||||
},
|
||||
"fingers_right": {
|
||||
"rotation": [0, -37.5, 0]
|
||||
@@ -80,37 +223,65 @@
|
||||
"rotation": [0, 30, 27.5]
|
||||
},
|
||||
"torso": {
|
||||
"rotation": [-2.5, 0, 0]
|
||||
"rotation": ["12.5+math.sin(q.anim_time*90*2)*0.5", 0, 0],
|
||||
"position": [0, "0+math.sin(q.anim_time*90*2+30)*-0.4", 0]
|
||||
},
|
||||
"chest": {
|
||||
"rotation": [-7.5, 0, 0]
|
||||
"rotation": ["-0+math.sin(q.anim_time*90*2-30)*1.5", 0, 0]
|
||||
},
|
||||
"hand_left": {
|
||||
"rotation": [0, -17.5, 0]
|
||||
"rotation": [0, "-17.5-math.sin(q.anim_time*90*2-60)*-2", 0]
|
||||
},
|
||||
"finger_front_left2": {
|
||||
"rotation": [0, -12.5, 0]
|
||||
"rotation": [0, "-12.5+math.sin(q.anim_time*90*2-150)*-5", 0]
|
||||
},
|
||||
"finger_middle_left2": {
|
||||
"rotation": [0, -10, 0]
|
||||
"rotation": [0, "-10+math.sin(q.anim_time*90*2-150)*-5", 0]
|
||||
},
|
||||
"finger_back_left2": {
|
||||
"rotation": [0, -15, 0]
|
||||
},
|
||||
"head_angle": {
|
||||
"rotation": [12.5, 0, 0]
|
||||
"rotation": [0, "-15+math.sin(q.anim_time*90*2-150)*-5", 0]
|
||||
},
|
||||
"hand_right": {
|
||||
"rotation": [0, 17.5, 0]
|
||||
"rotation": [0, "17.5+math.sin(q.anim_time*90*2-60)*-2", 0]
|
||||
},
|
||||
"finger_front_right2": {
|
||||
"rotation": [0, 12.5, 0]
|
||||
"rotation": [0, "12.5+math.sin(q.anim_time*90*2-150)*5", 0]
|
||||
},
|
||||
"finger_middle_right2": {
|
||||
"rotation": [0, 10, 0]
|
||||
"rotation": [0, "10+math.sin(q.anim_time*90*2-150)*5", 0]
|
||||
},
|
||||
"finger_back_right2": {
|
||||
"rotation": [0, 15, 0]
|
||||
"rotation": [0, "15+math.sin(q.anim_time*90*2-150)*5", 0]
|
||||
},
|
||||
"check_left_spike_front": {
|
||||
"rotation": [0, "0+math.sin(q.anim_time*90*2-30)*3", 0]
|
||||
},
|
||||
"check_left_spike_back": {
|
||||
"rotation": [0, "0+math.sin(q.anim_time*90*2-30)*3", 0]
|
||||
},
|
||||
"check_right_spike_front": {
|
||||
"rotation": [0, "0+math.sin(q.anim_time*90*2-30)*-3", 0]
|
||||
},
|
||||
"check_right_spike_back": {
|
||||
"rotation": [0, "0+math.sin(q.anim_time*90*2-30)*-3", 0]
|
||||
},
|
||||
"eyebrow_left": {
|
||||
"rotation": [0, "-2.5+math.sin(q.anim_time*90*2-60)*-2.5", 0]
|
||||
},
|
||||
"eyebrow_right": {
|
||||
"rotation": [0, "2.5-math.sin(q.anim_time*90*2-60)*-2.5", 0]
|
||||
},
|
||||
"tail": {
|
||||
"rotation": ["0+math.sin(q.anim_time*90*2-30)*-2.5", 0, 0]
|
||||
},
|
||||
"head": {
|
||||
"rotation": ["-5+math.sin(q.anim_time*90*2-90)*-2.5", "math.sin(q.anim_time*90*1-90)*-0.5", 0]
|
||||
},
|
||||
"eye_angry_left": {
|
||||
"position": [0, -0.1, 0]
|
||||
},
|
||||
"eye_angry_right": {
|
||||
"position": [0, -0.1, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -233,14 +404,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.swampert.cry": {
|
||||
"animation_length": 1.2,
|
||||
"sound_effects": {
|
||||
"0.04": {
|
||||
"effect": "pokemon.swampert.cry"
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.swampert.blink": {
|
||||
"animation_length": 0.1667,
|
||||
"bones": {
|
||||
@@ -322,6 +485,158 @@
|
||||
"position": [0, -0.1, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"animation.swampert.cry": {
|
||||
"animation_length": 2.5,
|
||||
"bones": {
|
||||
"chest2": {
|
||||
"rotation": {
|
||||
"0.0": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.2917": {
|
||||
"post": [7.5, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.625": {
|
||||
"post": [-5, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.5417": {
|
||||
"post": [-6, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"2.0417": {
|
||||
"post": [-1, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"2.5": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
}
|
||||
}
|
||||
},
|
||||
"neck": {
|
||||
"rotation": {
|
||||
"0.0": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.2917": {
|
||||
"post": [7.5, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.625": {
|
||||
"post": [-5, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.5417": {
|
||||
"post": [-6, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"2.0417": {
|
||||
"post": [-1, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"2.5": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
}
|
||||
}
|
||||
},
|
||||
"head": {
|
||||
"rotation": {
|
||||
"0.0": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.25": {
|
||||
"post": [7.5, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.5833": {
|
||||
"post": [-5, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.5": {
|
||||
"post": [-6, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"2.0": {
|
||||
"post": [1, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"2.5": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
}
|
||||
}
|
||||
},
|
||||
"eyelid_left": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.25": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0, -0.1, 0]
|
||||
},
|
||||
"0.4167": {
|
||||
"pre": [0, -0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"eyelid_right": {
|
||||
"position": {
|
||||
"0.0": [0, 0, 0],
|
||||
"0.25": {
|
||||
"pre": [0, 0, 0],
|
||||
"post": [0, -0.1, 0]
|
||||
},
|
||||
"0.4167": {
|
||||
"pre": [0, -0.1, 0],
|
||||
"post": [0, 0, 0]
|
||||
}
|
||||
}
|
||||
},
|
||||
"jaw": {
|
||||
"rotation": {
|
||||
"0.0": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.3333": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.6667": {
|
||||
"post": [30, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"0.9167": {
|
||||
"post": [15, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.4167": {
|
||||
"post": [40, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"1.8333": {
|
||||
"post": [40, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
},
|
||||
"2.1667": {
|
||||
"post": [0, 0, 0],
|
||||
"lerp_mode": "catmullrom"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"sound_effects": {
|
||||
"0.4167": {
|
||||
"effect": "pokemon.swampert.cry"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+938
-184
File diff suppressed because it is too large.
Load diff
Loaded 100 of 1074 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user