Compare commits
22
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2e80924c68 | ||
|
|
6749b39142 | ||
|
|
ff25416b07 | ||
|
|
bb81a44a11 | ||
|
|
40dfca2294 | ||
|
|
5a40ced96b | ||
|
|
3eb97b29a1 | ||
|
|
d88de0b072 | ||
|
|
460c44248c | ||
|
|
a16668695c | ||
|
|
fe5ebb5444 | ||
|
|
c34e4c8bbc | ||
|
|
84e76a0a6d | ||
|
|
be70c1e8de | ||
|
|
fba40387bb | ||
|
|
1217e6d101 | ||
|
|
905c410aee | ||
|
|
cea0c826c6 | ||
|
|
dc3b17df3b | ||
|
|
5602dee9ac | ||
|
|
9e4137cc20 | ||
|
|
c92248f6e9 |
No files matched your search
+3
-12
@@ -42,8 +42,9 @@
|
||||
- All ruin structures gilded chest loot tables have been updated to include a guaranteed TM not learned naturally by any Pokémon through their level-up moveset. Each ruin gets its own specific TM, so you can now go hunting ruins to complete your move dex!
|
||||
- All fossil structures have been transferred over to biome features, allowing for better placement in generation.
|
||||
- The prehistoric_underwater_fissure & prehistoric_submerged_impact fossil structures now use the biome tag `#cobblemon:is_temperate_ocean`.
|
||||
- A new Biome tag called `#cobblemon:is_stony_beach` has been added.
|
||||
- Gimmighoul towers now generate at ground level rather than sinking one block into the ground.
|
||||
- A new shipwreck cove structure called the "magma_shipwreck_cove" has been added.
|
||||
- 1 New shipwreck cove structure called the "magma_shipwreck_cove" has been added.
|
||||
- Shipwreck coves now generate slightly more frequently.
|
||||
- Added equipment loot tables for shipwreck cove enemies.
|
||||
- Maps from abandoned fishing boats leading to shipwreck coves now will skip explored chunks, allowing the player to find more shipwreck coves easier.
|
||||
@@ -56,7 +57,6 @@
|
||||
- Pokémon cries now play when clicking Pokémon in the summary screen.
|
||||
- Pressing the Summary key while either the starter selection or summary screen are open now closes those screens
|
||||
- Ice type Pokémon are now immune to Packed Snow
|
||||
- Held item visibility can now be controlled by the held_item_visible command argument.
|
||||
|
||||
### New rideable Pokémon
|
||||
- Drampa
|
||||
@@ -301,12 +301,6 @@
|
||||
- Resolved Z-Fighting on Pokédex Models
|
||||
- Restored Ninjask's ability to do barrel rolls
|
||||
- Fixed a crash caused by adding enchanted items to the Resurrection Machine
|
||||
- Fixed a crash that could occur when starting a PvN battle with only fainted Pokémon.
|
||||
- Fixed the Remember Riding Camera config not being respected when dismounting and resolved the incompatibility with the Auto Third Person mod
|
||||
- Fixed Full Heal block not dropping Full Heals
|
||||
- Fixed status cure items not returning an empty bottle when used
|
||||
- Fixed Panpour consuming its held item when evolving with a Water Stone
|
||||
- Fixed Smoked Tail Curry returning a Wooden Bowl when consumed despite it not being included in the recipe
|
||||
|
||||
### Fixes
|
||||
- Fixed Croagunk's walkspeed
|
||||
@@ -357,8 +351,6 @@
|
||||
- Fixed Guilded chests being more accessible than intended
|
||||
- Fixed fished up Pokémon not being added as "seen" to the Pokedex
|
||||
- Fixed surprised Gimmighoul encounters not being added as "seen" to the Pokedex
|
||||
- Fixed a crash involving berry trees that have been world edited.
|
||||
- Fixed visual desync in multiplayer for players mounting Pokémon outside other players' loaded chunks
|
||||
|
||||
### Developer
|
||||
- Added `PokeSnackSpawnerFactory` which allows influence registration on PokeSnack encounters
|
||||
@@ -369,8 +361,7 @@
|
||||
- Separated all the functions of MoLangFunctions.kt into their own files.
|
||||
- Spawn buckets and their base weights are now provided by the spawner, with different base weights for world, fishing, snack, and habitat spawn buckets.
|
||||
- Removed "SpawnBucket" class in favour of just storing maps of bucket names to weights.
|
||||
- Fixed nicknames not being applied to Pokémon spawned from `spawn_pool_world` files.
|
||||
- Added support for `profilePokedexScale`, `profilePokedexTranslation`, `profileSummaryScale`, and `profileSummaryTranslation` in poser files for finer control over profile displays.
|
||||
- Fixed nicknames not being applied to Pokémon spawned from `spawn_pool_world` files
|
||||
|
||||
### Molang & Datapacks
|
||||
- Added `moveset_builders` datapack folder for different styles of movesets.
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.cobblemon.mod.common.Cobblemon;
|
||||
import com.cobblemon.mod.common.OrientationControllable;
|
||||
import com.cobblemon.mod.common.api.orientation.OrientationController;
|
||||
import com.cobblemon.mod.common.client.CobblemonClient;
|
||||
import com.cobblemon.mod.common.client.gui.interact.wheel.InteractWheelGuiFactoryKt;
|
||||
import com.cobblemon.mod.common.client.keybind.keybinds.PartySendBinding;
|
||||
import com.cobblemon.mod.common.client.keybind.keybinds.RidingFreelookBinding;
|
||||
import com.cobblemon.mod.common.duck.RidePassenger;
|
||||
@@ -67,6 +68,39 @@ public abstract class MouseHandlerMixin {
|
||||
|
||||
@Unique private double cobblemon$timeDelta;
|
||||
|
||||
@Inject(
|
||||
method = "onPress",
|
||||
at = @At("HEAD"),
|
||||
cancellable = true
|
||||
)
|
||||
public void cobblemon$pokeskillGuiControl(long windowPointer, int button, int action, int modifiers, CallbackInfo ci) {
|
||||
if (button == 0 && action == 1) {
|
||||
|
||||
// Make sure no menus are open already
|
||||
if (this.minecraft.screen == null && this.minecraft.getOverlay() == null) {
|
||||
// Check to see if party key is held
|
||||
if (PartySendBinding.INSTANCE.getWasDown()) {
|
||||
|
||||
// Don't want to send out a pokemon if we let go of the key
|
||||
PartySendBinding.INSTANCE.actioned();
|
||||
|
||||
//Open the actual gui
|
||||
var player = Minecraft.getInstance().player;
|
||||
var storage = CobblemonClient.INSTANCE.getStorage();
|
||||
var selectedPokemon = storage.getParty().get(storage.getSelectedSlot());
|
||||
if (selectedPokemon != null && player != null) {
|
||||
//canApplyChange = false
|
||||
var gui = InteractWheelGuiFactoryKt.createPokeSkillGui(player, selectedPokemon);
|
||||
Minecraft.getInstance().setScreen(gui);
|
||||
}
|
||||
|
||||
// Stop the rest of minecraft click logic like punching and using items
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "onScroll",
|
||||
at = @At(
|
||||
|
||||
@@ -108,7 +108,6 @@ import com.cobblemon.mod.common.pokemon.helditem.CobblemonHeldItemManager
|
||||
import com.cobblemon.mod.common.pokemon.properties.AspectPropertyType
|
||||
import com.cobblemon.mod.common.pokemon.properties.BattleCloneProperty
|
||||
import com.cobblemon.mod.common.pokemon.properties.FreezeFrameProperty
|
||||
import com.cobblemon.mod.common.pokemon.properties.HeldItemVisibleProperty
|
||||
import com.cobblemon.mod.common.pokemon.properties.HiddenAbilityPropertyType
|
||||
import com.cobblemon.mod.common.pokemon.properties.LabelProperty
|
||||
import com.cobblemon.mod.common.pokemon.properties.NoAIProperty
|
||||
@@ -351,7 +350,6 @@ object Cobblemon {
|
||||
CustomPokemonProperty.register(UnaspectPropertyType)
|
||||
CustomPokemonProperty.register(FreezeFrameProperty)
|
||||
CustomPokemonProperty.register(NoAIProperty)
|
||||
CustomPokemonProperty.register(HeldItemVisibleProperty)
|
||||
|
||||
CobblemonEvents.POKEMON_PROPERTY_INITIALISED.emit(Unit)
|
||||
|
||||
|
||||
@@ -405,7 +405,7 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
@JvmField
|
||||
val BIG_MALASADA = regionalFoodItem("big_malasada", 64, 7, 0.3f, false)
|
||||
@JvmField
|
||||
val SMOKED_TAIL_CURRY = regionalFoodItem("smoked_tail_curry", 64, 10, 0.6f, false)
|
||||
val SMOKED_TAIL_CURRY = regionalFoodItem("smoked_tail_curry", 64, 10, 0.6f, false, ItemStack(Items.BOWL, 1))
|
||||
@JvmField
|
||||
val JUBILIFE_MUFFIN = regionalFoodItem("jubilife_muffin", 64, 7, 0.3f, false)
|
||||
@JvmField
|
||||
|
||||
@@ -24,27 +24,13 @@ import com.cobblemon.mod.common.client.net.data.RideSettingsSyncHandler
|
||||
import com.cobblemon.mod.common.client.net.debug.OpenRidingStatsDebugGUIHandler
|
||||
import com.cobblemon.mod.common.client.net.dialogue.DialogueClosedHandler
|
||||
import com.cobblemon.mod.common.client.net.dialogue.DialogueOpenedHandler
|
||||
import com.cobblemon.mod.common.client.net.effect.PokeSnackBlockParticlesHandler
|
||||
import com.cobblemon.mod.common.client.net.effect.RunPosableMoLangHandler
|
||||
import com.cobblemon.mod.common.client.net.effect.SaccharineLogBlockParticlesHandler
|
||||
import com.cobblemon.mod.common.client.net.effect.SpawnSnowstormEntityParticleHandler
|
||||
import com.cobblemon.mod.common.client.net.effect.SpawnSnowstormParticleHandler
|
||||
import com.cobblemon.mod.common.client.net.gui.ExpGainedDataPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.gui.InteractPokemonUIPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.gui.PokedexUIPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.gui.SetActiveTMPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.gui.SetTMMachineContainerDataPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.gui.SummaryUIPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.gui.SynchronizeActiveTMHandler
|
||||
import com.cobblemon.mod.common.client.net.effect.*
|
||||
import com.cobblemon.mod.common.client.net.gui.*
|
||||
import com.cobblemon.mod.common.client.net.habitat.OpenHabitatBlockEditorHandler
|
||||
import com.cobblemon.mod.common.client.net.npc.CloseNPCEditorHandler
|
||||
import com.cobblemon.mod.common.client.net.npc.OpenNPCEditorHandler
|
||||
import com.cobblemon.mod.common.client.net.orientation.ClientboundUpdateOrientationHandler
|
||||
import com.cobblemon.mod.common.client.net.pasture.ClosePastureHandler
|
||||
import com.cobblemon.mod.common.client.net.pasture.OpenPastureHandler
|
||||
import com.cobblemon.mod.common.client.net.pasture.PokemonPasturedHandler
|
||||
import com.cobblemon.mod.common.client.net.pasture.PokemonUnpasturedHandler
|
||||
import com.cobblemon.mod.common.client.net.pasture.UpdatePastureConflictFlagHandler
|
||||
import com.cobblemon.mod.common.client.net.pasture.*
|
||||
import com.cobblemon.mod.common.client.net.pokedex.ServerConfirmedRegisterHandler
|
||||
import com.cobblemon.mod.common.client.net.pokemon.update.ClientboundSeatAssignmentPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.pokemon.update.ClientboundUpdateRidingStateHandler
|
||||
@@ -63,14 +49,7 @@ import com.cobblemon.mod.common.client.net.storage.party.SetPartyPokemonHandler
|
||||
import com.cobblemon.mod.common.client.net.storage.party.SetPartyReferenceHandler
|
||||
import com.cobblemon.mod.common.client.net.storage.pc.*
|
||||
import com.cobblemon.mod.common.client.net.toast.ToastPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeAcceptanceChangedHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeCancelledHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeCompletedHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeOfferExpiredHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeOfferNotificationHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeProcessStartedHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeStartedHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.TradeUpdatedHandler
|
||||
import com.cobblemon.mod.common.client.net.trade.*
|
||||
import com.cobblemon.mod.common.net.PacketRegisterInfo
|
||||
import com.cobblemon.mod.common.net.messages.client.OpenBehaviourEditorPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.PlayerInteractOptionsPacket
|
||||
@@ -86,21 +65,13 @@ import com.cobblemon.mod.common.net.messages.client.data.*
|
||||
import com.cobblemon.mod.common.net.messages.client.debug.RequestOpenRidingStatsDebugGUIPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.dialogue.DialogueClosedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.dialogue.DialogueOpenedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.PokeSnackBlockParticlesPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.RunPosableMoLangPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.SaccharineLogBlockParticlesPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormEntityParticlePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormParticlePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.*
|
||||
import com.cobblemon.mod.common.net.messages.client.habitat.OpenHabitatBlockEditorPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.npc.CloseNPCEditorPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.npc.OpenNPCEditorPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.orientation.ClientboundUpdateDriverInputPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.orientation.ClientboundUpdateOrientationPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pasture.ClosePasturePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pasture.OpenPasturePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pasture.PokemonPasturedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pasture.PokemonUnpasturedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pasture.UpdatePastureConflictFlagPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pasture.*
|
||||
import com.cobblemon.mod.common.net.messages.client.pokedex.ServerConfirmedRegisterPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.pokemon.update.*
|
||||
import com.cobblemon.mod.common.net.messages.client.pokemon.update.evolution.AddEvolutionPacket
|
||||
@@ -121,47 +92,17 @@ import com.cobblemon.mod.common.net.messages.client.storage.party.InitializePart
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.party.MoveClientPartyPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.party.SetPartyPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.party.SetPartyReferencePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.ClosePCPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.InitializePCPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.MoveClientPCPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.OpenPCPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.RenamePCBoxPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.SetPCBoxPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.SetPCPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.*
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.ChangePCBoxWallpaperPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.RequestPCBoxWallpapersPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.SetPCBoxWallpapersPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.storage.pc.wallpaper.UnlockPCBoxWallpaperPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.tms.TechnicalMachineRegistrySyncPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.toast.ToastPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeAcceptanceChangedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeCancelledPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeCompletedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeOfferExpiredPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeOfferNotificationPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeProcessStartedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeStartedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.TradeUpdatedPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.ExpGainedDataPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.InteractPokemonUIPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.PokedexUIPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.SetActiveTMPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.SetTMMachineContainerDataPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.SummaryUIPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.SynchronizeActiveTMPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.BattleChallengePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.BattleChallengeResponsePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.BenchMovePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.RequestMoveSwapPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.RequestPlayerInteractionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.SelectStarterPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.SendOutPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.BattleSelectActionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamLeavePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamRequestPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.BattleTeamResponsePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.RemoveSpectatorPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.SpectateBattlePacket
|
||||
import com.cobblemon.mod.common.net.messages.client.trade.*
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.*
|
||||
import com.cobblemon.mod.common.net.messages.server.*
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.*
|
||||
import com.cobblemon.mod.common.net.messages.server.behaviour.DamageOnCollisionPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.behaviour.SetEntityBehaviourPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.block.AdjustBlockEntityViewerCountPacket
|
||||
@@ -188,11 +129,7 @@ import com.cobblemon.mod.common.net.messages.server.pasture.UnpasturePokemonPack
|
||||
import com.cobblemon.mod.common.net.messages.server.pokedex.scanner.FinishScanningPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokedex.scanner.StartScanningPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.interact.InteractPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.ServerboundUpdateRidingStatePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetActiveMarkPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetItemHiddenPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetMarkingsPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetNicknamePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.*
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.evolution.AcceptEvolutionPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.riding.DismountPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.riding.ServerboundUpdateDriverInputPacket
|
||||
@@ -205,21 +142,12 @@ import com.cobblemon.mod.common.net.messages.server.storage.party.PartyTutorialP
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.party.ReleasePartyPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.party.SwapPartyPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.pc.*
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.AcceptTradeRequestPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.CancelTradePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.ChangeTradeAcceptancePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.OfferTradePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.PerformTradePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.UpdateTradeOfferPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.*
|
||||
import com.cobblemon.mod.common.net.serverhandling.ChallengeHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.ChallengeResponseHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.RequestInteractionsHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.BattleSelectActionsHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.RemoveSpectatorHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.SpectateBattleHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.TeamLeaveHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.TeamRequestHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.TeamRequestResponseHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.UsePokeSkillHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.battle.*
|
||||
import com.cobblemon.mod.common.net.serverhandling.behaviour.DamageOnCollisionPacketHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.behaviour.SetEntityBehaviourHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.block.AdjustBlockEntityViewerCountHandler
|
||||
@@ -247,11 +175,7 @@ import com.cobblemon.mod.common.net.serverhandling.pasture.UnpasturePokemonHandl
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokedex.scanner.FinishScanningHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokedex.scanner.StartScanningHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokemon.interact.InteractPokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.ServerboundUpdateRidingStateHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetActiveMarkHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetItemHiddenHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetMarkingsHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetNicknameHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.*
|
||||
import com.cobblemon.mod.common.net.serverhandling.riding.DismountPokemonPacketHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.riding.DriverInputPacketHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.riding.ServerboundUpdatePassengerPositionHandler
|
||||
@@ -267,12 +191,7 @@ import com.cobblemon.mod.common.net.serverhandling.storage.party.PartyTutorialPa
|
||||
import com.cobblemon.mod.common.net.serverhandling.storage.party.ReleasePCPokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.storage.party.SwapPartyPokemonHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.storage.pc.*
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.AcceptTradeRequestHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.CancelTradeHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.ChangeTradeAcceptanceHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.OfferTradeHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.PerformTradeHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.UpdateTradeOfferHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.trade.*
|
||||
import com.cobblemon.mod.common.util.server
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
@@ -342,6 +261,7 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(MarkingsUpdatePacket.ID, MarkingsUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
list.add(PacketRegisterInfo(RideBoostsUpdatePacket.ID, RideBoostsUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
list.add(PacketRegisterInfo(RideStaminaUpdatePacket.ID, RideStaminaUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
list.add(PacketRegisterInfo(SkillCooldownsUpdatePacket.ID, SkillCooldownsUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
list.add(PacketRegisterInfo(AlphaUpdatePacket.ID, AlphaUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
list.add(PacketRegisterInfo(ScaleModifierUpdatePacket.ID, ScaleModifierUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
|
||||
@@ -377,7 +297,6 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(PlayerInteractOptionsPacket.ID, PlayerInteractOptionsPacket::decode, PlayerInteractOptionsHandler))
|
||||
list.add(PacketRegisterInfo(PokedexUIPacket.ID, PokedexUIPacket::decode, PokedexUIPacketHandler))
|
||||
list.add(PacketRegisterInfo(ExpGainedDataPacket.ID, ExpGainedDataPacket::decode, ExpGainedDataPacketHandler))
|
||||
list.add(PacketRegisterInfo(SynchronizeActiveTMPacket.ID, SynchronizeActiveTMPacket::decode, SynchronizeActiveTMHandler))
|
||||
|
||||
// Starter packets
|
||||
list.add(PacketRegisterInfo(OpenStarterUIPacket.ID, OpenStarterUIPacket::decode, StarterUIPacketHandler))
|
||||
@@ -443,6 +362,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(PokeSkillsRegistrySyncPacket.ID, PokeSkillsRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(TechnicalMachineRegistrySyncPacket.ID, TechnicalMachineRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
|
||||
// Effects
|
||||
@@ -535,6 +455,7 @@ object CobblemonNetwork {
|
||||
// Interaction Packets
|
||||
list.add(PacketRegisterInfo(InteractPokemonPacket.ID, InteractPokemonPacket::decode, InteractPokemonHandler))
|
||||
list.add(PacketRegisterInfo(RequestPlayerInteractionsPacket.ID, RequestPlayerInteractionsPacket::decode, RequestInteractionsHandler))
|
||||
list.add(PacketRegisterInfo(UsePokeSkillPacket.ID, UsePokeSkillPacket::decode, UsePokeSkillHandler))
|
||||
|
||||
// Storage Packets
|
||||
list.add(PacketRegisterInfo(SendOutPokemonPacket.ID, SendOutPokemonPacket::decode, SendOutPokemonHandler))
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonNetwork.sendPacket
|
||||
import com.cobblemon.mod.common.api.data.JsonDataRegistry
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectTimeline
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokeSkill
|
||||
import com.cobblemon.mod.common.net.messages.client.data.PokeSkillsRegistrySyncPacket
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.adapters.ActionEffectTimelineAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.ExpressionLikeAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.TextAdapter
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.packs.PackType
|
||||
import net.minecraft.world.entity.player.Player
|
||||
|
||||
/**
|
||||
* The JSON data registry for all the possible [PokeSkill]s.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since August 31st, 2025
|
||||
*/
|
||||
object CobblemonPokeSkills : JsonDataRegistry<PokeSkill> {
|
||||
override val id = cobblemonResource("poke_skills")
|
||||
override val type = PackType.SERVER_DATA
|
||||
override val observable = SimpleObservable<CobblemonPokeSkills>()
|
||||
override val typeToken = TypeToken.get(PokeSkill::class.java)
|
||||
override val resourcePath = "poke_skills"
|
||||
override val gson = GsonBuilder()
|
||||
.setPrettyPrinting()
|
||||
.registerTypeAdapter(ExpressionLike::class.java, ExpressionLikeAdapter)
|
||||
.registerTypeAdapter(ActionEffectTimeline::class.java, ActionEffectTimelineAdapter)
|
||||
.registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter)
|
||||
.registerTypeAdapter(Component::class.java, TextAdapter)
|
||||
.create()
|
||||
|
||||
var skills = mapOf<ResourceLocation, PokeSkill>()
|
||||
|
||||
fun getAccessibleSkills(player: Player, pokemon: Pokemon): List<PokeSkill> {
|
||||
return skills.values.filter { it.canAccess(player, pokemon) }
|
||||
}
|
||||
|
||||
override fun reload(data: Map<ResourceLocation, PokeSkill>) {
|
||||
data.forEach { (id, skill) -> skill.id = id }
|
||||
skills = data
|
||||
observable.emit(this)
|
||||
Cobblemon.LOGGER.info("Loaded ${skills.size} PokéSkills")
|
||||
}
|
||||
|
||||
override fun sync(player: ServerPlayer) {
|
||||
player.sendPacket(PokeSkillsRegistrySyncPacket(skills.values.toList()))
|
||||
}
|
||||
}
|
||||
@@ -69,7 +69,7 @@ class HabitatPool {
|
||||
pool.spawns = spawns
|
||||
return pool
|
||||
} else {
|
||||
return HabitatPools.habitatPoolsById[poolId] ?: default()
|
||||
return HabitatPools.habitatPoolsById[poolId] ?: HabitatPool.default()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -94,14 +94,6 @@ class HabitatPool {
|
||||
return spawns.mapNotNull { it.createSpawnDetail(habitatBlockEntity) }
|
||||
}
|
||||
|
||||
fun getPhaseCount(): Int {
|
||||
return spawns
|
||||
.flatMap { it.phases?.ranges?.flatten() ?: emptySet() }
|
||||
.toSet()
|
||||
.count()
|
||||
.coerceAtLeast(1)
|
||||
}
|
||||
|
||||
fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeResourceLocation(id)
|
||||
buffer.writeUtf(name)
|
||||
|
||||
@@ -17,6 +17,7 @@ import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
class HabitatSettingsDTO() {
|
||||
var numberOfPhases = 1
|
||||
var phaseOrder = HabitatPhaseOrder.SIMPLE
|
||||
lateinit var levelRange: IntRange
|
||||
var modifiers: String = ""
|
||||
@@ -27,6 +28,7 @@ class HabitatSettingsDTO() {
|
||||
var naturalSettings: NaturalHabitatSettingsDTO? = null
|
||||
|
||||
constructor(habitatBlockEntity: HabitatBlockEntity) : this() {
|
||||
this.numberOfPhases = habitatBlockEntity.numberOfPhases
|
||||
this.phaseOrder = habitatBlockEntity.phaseOrder
|
||||
this.levelRange = habitatBlockEntity.levelRange
|
||||
this.modifiers = habitatBlockEntity.modifiers.asString()
|
||||
@@ -42,6 +44,7 @@ class HabitatSettingsDTO() {
|
||||
}
|
||||
|
||||
fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeInt(numberOfPhases)
|
||||
buffer.writeEnum(phaseOrder)
|
||||
buffer.writeInt(levelRange.first)
|
||||
buffer.writeInt(levelRange.last)
|
||||
@@ -57,6 +60,7 @@ class HabitatSettingsDTO() {
|
||||
}
|
||||
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
this.numberOfPhases = buffer.readInt()
|
||||
this.phaseOrder = buffer.readEnum(HabitatPhaseOrder::class.java)
|
||||
val levelRangeStart = buffer.readInt()
|
||||
val levelRangeEnd = buffer.readInt()
|
||||
|
||||
@@ -293,11 +293,11 @@ object MoLangFunctions {
|
||||
)
|
||||
value.functions["is_in"] = Function put@{ params: MoParams ->
|
||||
val tag = TagKey.create(key, ResourceLocation.parse(params.getString(0).replace("#", "")))
|
||||
return@put DoubleValue(if (value.obj.`is`(tag)) 1.0 else 0.0)
|
||||
return@put DoubleValue(value.obj.`is`(tag))
|
||||
}
|
||||
value.functions["is_of"] = Function put@{ params: MoParams ->
|
||||
val identifier = ResourceLocation.parse(params.getString(0))
|
||||
return@put DoubleValue(if (value.obj.`is`(identifier)) 1.0 else 0.0)
|
||||
return@put DoubleValue(value.obj.`is`(identifier))
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ object DropEntryMoLangFunctions : AbstractMoLangFunctionHolder<DropEntry>() {
|
||||
map["max_selectable_times"] = { DoubleValue(drop.maxSelectableTimes.toDouble()) }
|
||||
map["can_drop"] = { params ->
|
||||
val pokemon = params.getOrNull<ObjectValue<Pokemon>>(0)?.obj
|
||||
DoubleValue(if (drop.canDrop(pokemon)) 1.0 else 0.0)
|
||||
DoubleValue(drop.canDrop(pokemon))
|
||||
}
|
||||
return map
|
||||
}
|
||||
|
||||
+67
-1
@@ -35,12 +35,14 @@ import com.cobblemon.mod.common.util.effectiveName
|
||||
import com.cobblemon.mod.common.util.getBlockStatesWithPos
|
||||
import com.cobblemon.mod.common.util.getBooleanOrNull
|
||||
import com.cobblemon.mod.common.util.getDoubleOrNull
|
||||
import com.cobblemon.mod.common.util.getIntOrNull
|
||||
import com.cobblemon.mod.common.util.getIsSubmerged
|
||||
import com.cobblemon.mod.common.util.getOrNull
|
||||
import com.cobblemon.mod.common.util.getStringOrNull
|
||||
import com.cobblemon.mod.common.util.isStandingOn
|
||||
import com.cobblemon.mod.common.util.resolve
|
||||
import com.cobblemon.mod.common.util.worldRegistry
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
@@ -48,7 +50,10 @@ import net.minecraft.tags.TagKey
|
||||
import net.minecraft.world.damagesource.DamageSource
|
||||
import net.minecraft.world.damagesource.DamageTypes
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.TamableAnimal
|
||||
import net.minecraft.world.level.block.BonemealableBlock
|
||||
import net.minecraft.world.level.block.CropBlock
|
||||
import net.minecraft.world.phys.AABB
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import java.util.UUID
|
||||
@@ -78,8 +83,13 @@ object EntityMoLangFunctions : AbstractMoLangFunctionHolder<Entity>() {
|
||||
"vertical_velocity" to { DoubleValue(thisEntity.deltaMovement.y) },
|
||||
"is_on_ground" to { _ -> DoubleValue(thisEntity.onGround()) },
|
||||
"world" to { _ -> thisEntity.level().worldRegistry.wrapAsHolder(thisEntity.level()).asWorldMoLangValue() },
|
||||
"dimension" to { StringValue(thisEntity.level().dimension().location().toString()) },
|
||||
"biome" to { _ -> thisEntity.level().getBiome(thisEntity.blockPosition()).asBiomeMoLangValue() },
|
||||
"is_passenger" to { DoubleValue(thisEntity.isPassenger) },
|
||||
"is_passenger" to isPassenger@{ params ->
|
||||
val passengerEntity = (params.get<MoValue>(0) as? ObjectValue<*>)?.obj as? LivingEntity ?: return@isPassenger DoubleValue.ZERO
|
||||
DoubleValue(passengerEntity in thisEntity.passengers)
|
||||
},
|
||||
"discard" to { thisEntity.discard() },
|
||||
"is_sneaking" to { _ -> DoubleValue(thisEntity.isShiftKeyDown) },
|
||||
"is_sprinting" to { _ -> DoubleValue(thisEntity.isSprinting) },
|
||||
@@ -121,6 +131,62 @@ object EntityMoLangFunctions : AbstractMoLangFunctionHolder<Entity>() {
|
||||
listOf(thisEntity.deltaMovement.x, thisEntity.deltaMovement.y, thisEntity.deltaMovement.z)
|
||||
.asArrayValue(::DoubleValue)
|
||||
},
|
||||
"set_position" to { params ->
|
||||
val x = params.getDouble(0)
|
||||
val y = params.getDouble(1)
|
||||
val z = params.getDouble(2)
|
||||
thisEntity.setPos(x, y, z)
|
||||
DoubleValue.ONE
|
||||
},
|
||||
"fertilize_nearby_crops" to { params -> //TODO: pretty bespoke. Maybe should be moved or generalized?
|
||||
val radius = params.getIntOrNull(0) ?: 8
|
||||
val maxCrops = params.getIntOrNull(1) ?: 8
|
||||
|
||||
var fertilizedCount = 0
|
||||
val level = thisEntity.level()
|
||||
val centerPos = thisEntity.blockPosition()
|
||||
|
||||
// Find all bonemealable blocks within radius
|
||||
val bonemealableBlocks = mutableListOf<BlockPos>()
|
||||
|
||||
for (x in -radius..radius) {
|
||||
for (y in -3..3) { // Limited vertical range
|
||||
for (z in -radius..radius) {
|
||||
val pos = centerPos.offset(x, y, z)
|
||||
val blockState = level.getBlockState(pos)
|
||||
val block = blockState.block
|
||||
|
||||
// Check if block can be bonemealed
|
||||
if (block is BonemealableBlock && block is CropBlock && block.isValidBonemealTarget(level, pos, blockState)) {
|
||||
bonemealableBlocks.add(pos)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Shuffle and take up to maxCrops blocks to fertilize
|
||||
bonemealableBlocks.shuffle()
|
||||
val blocksToFertilize = bonemealableBlocks.take(maxCrops)
|
||||
|
||||
for (pos in blocksToFertilize) {
|
||||
val blockState = level.getBlockState(pos)
|
||||
val block = blockState.block
|
||||
|
||||
if (block is BonemealableBlock && block.isValidBonemealTarget(level, pos, blockState)) {
|
||||
if (block.isBonemealSuccess(level, level.random, pos, blockState)) {
|
||||
block.performBonemeal(level as ServerLevel, level.random, pos, blockState)
|
||||
|
||||
// Add bonemeal particle
|
||||
val particlePos = block.getParticlePos(pos)
|
||||
level.levelEvent(1505, particlePos, 15) // Same event used for bonemealing in vanilla
|
||||
|
||||
fertilizedCount++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DoubleValue(fertilizedCount.toDouble())
|
||||
},
|
||||
"tags" to {
|
||||
val tags = thisEntity.tags
|
||||
val array = ArrayStruct(hashMapOf())
|
||||
@@ -233,7 +299,7 @@ object EntityMoLangFunctions : AbstractMoLangFunctionHolder<Entity>() {
|
||||
val intangible = params.getBooleanOrNull(0) ?: true
|
||||
thisEntity.noPhysics = intangible
|
||||
DoubleValue.ONE
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
|
||||
+18
@@ -39,6 +39,7 @@ import net.minecraft.world.entity.Mob
|
||||
import net.minecraft.world.entity.PathfinderMob
|
||||
import net.minecraft.world.entity.TamableAnimal
|
||||
import net.minecraft.world.entity.ai.behavior.BlockPosTracker
|
||||
import net.minecraft.world.entity.ai.behavior.EntityTracker
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.entity.ai.memory.MemoryStatus
|
||||
import net.minecraft.world.entity.ai.memory.WalkTarget
|
||||
@@ -123,6 +124,23 @@ object LivingEntityMoLangFunctions : AbstractMoLangFunctionHolder<LivingEntity>(
|
||||
duration.toLong()
|
||||
)
|
||||
}
|
||||
map["look_at_entity"] = put@{ params ->
|
||||
val targetEntity = params.get<MoValue>(0)
|
||||
val duration = params.getDoubleOrNull(1)?.toInt() ?: 20
|
||||
|
||||
val lookEntity = if (targetEntity is ObjectValue<*> && targetEntity.obj is Entity) {
|
||||
targetEntity.obj as Entity
|
||||
} else {
|
||||
return@put DoubleValue.ZERO
|
||||
}
|
||||
|
||||
// Set the current entity to track the looked for entity
|
||||
val brain = entity.brain
|
||||
val tracker = EntityTracker(lookEntity, true)
|
||||
brain.setMemoryWithExpiry(MemoryModuleType.LOOK_TARGET, tracker, duration.toLong())
|
||||
|
||||
DoubleValue.ONE
|
||||
}
|
||||
map["get_wander_control_memory"] = put@{
|
||||
val value = entity.brain.getMemorySafely(CobblemonMemories.WANDER_CONTROL).orElse(null)
|
||||
?: CobblemonWanderControl()
|
||||
|
||||
+62
@@ -23,6 +23,7 @@ import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.battles.BattleBuilder
|
||||
import com.cobblemon.mod.common.battles.BattleFormat
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.entity.npc.NPCEntity
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.net.messages.client.battle.BattleMusicPacket
|
||||
@@ -32,6 +33,7 @@ import com.cobblemon.mod.common.util.activeDialogue
|
||||
import com.cobblemon.mod.common.util.asBlockPos
|
||||
import com.cobblemon.mod.common.util.asResource
|
||||
import com.cobblemon.mod.common.util.asUUID
|
||||
import com.cobblemon.mod.common.util.blockRegistry
|
||||
import com.cobblemon.mod.common.util.getBattleState
|
||||
import com.cobblemon.mod.common.util.getBooleanOrNull
|
||||
import com.cobblemon.mod.common.util.getDoubleOrNull
|
||||
@@ -44,14 +46,19 @@ import com.cobblemon.mod.common.util.party
|
||||
import com.cobblemon.mod.common.util.pc
|
||||
import com.cobblemon.mod.common.util.pokedex
|
||||
import com.cobblemon.mod.common.util.server
|
||||
import com.cobblemon.mod.common.util.toArrayStruct
|
||||
import net.minecraft.client.player.AbstractClientPlayer
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.sounds.SoundSource
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.level.ClipContext
|
||||
import net.minecraft.world.level.GameType
|
||||
import net.minecraft.world.phys.HitResult
|
||||
import kotlin.collections.iterator
|
||||
|
||||
object PlayerMoLangFunctions : AbstractMoLangFunctionHolder<Player>() {
|
||||
@@ -379,6 +386,61 @@ object PlayerMoLangFunctions : AbstractMoLangFunctionHolder<Player>() {
|
||||
} ?: DoubleValue.ZERO
|
||||
}
|
||||
map["has_chosen_starter"] = { _ -> DoubleValue(Cobblemon.playerDataManager.getGenericData(player).starterSelected) }
|
||||
map["ride"] = put@{ params ->
|
||||
val entity = (params.get<MoValue>(0) as? ObjectValue<*>)?.obj as? Entity ?: return@put DoubleValue.ZERO
|
||||
player.startRiding(entity)
|
||||
}
|
||||
map["has_respawn_position"] = {
|
||||
DoubleValue(player.respawnPosition != null)
|
||||
}
|
||||
map["respawn_position"] = {
|
||||
player.respawnPosition?.toArrayStruct() ?: DoubleValue.ZERO
|
||||
}
|
||||
map["respawn_dimension"] = {
|
||||
StringValue(player.respawnDimension.location().toString())
|
||||
}
|
||||
map["teleport_to_respawn"] = put@{
|
||||
val respawnPosition = player.respawnPosition?.center ?: return@put DoubleValue.ZERO
|
||||
player.teleportTo(respawnPosition.x, respawnPosition.y, respawnPosition.z)
|
||||
DoubleValue.ONE
|
||||
}
|
||||
map["get_looked_block"] = put@{ params ->
|
||||
// Get the block the player is looking at 'distance' units away
|
||||
val distance = params.getDoubleOrNull(0) ?: 8.0
|
||||
|
||||
// perform clip
|
||||
val level = player.level()
|
||||
val eye = player.eyePosition
|
||||
val view = player.getViewVector(1.0f)
|
||||
val lookPos = eye.add(view.scale(distance))
|
||||
val hitResult = level.clip(ClipContext(eye, lookPos, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, player))
|
||||
|
||||
if (hitResult.type == HitResult.Type.BLOCK) {
|
||||
// Get base block info
|
||||
val blockPos = hitResult.blockPos
|
||||
val blockState = level.getBlockState(blockPos)
|
||||
val blockHolder = level.blockRegistry.wrapAsHolder(blockState.block)
|
||||
val blockValue = blockHolder.asMoLangValue(Registries.BLOCK)
|
||||
|
||||
// Attach the position to the blockValue return
|
||||
blockValue.addFunction("x") { DoubleValue(blockPos.x.toDouble()) }
|
||||
blockValue.addFunction("y") { DoubleValue(blockPos.y.toDouble()) }
|
||||
blockValue.addFunction("z") { DoubleValue(blockPos.z.toDouble()) }
|
||||
|
||||
return@put blockValue
|
||||
} else {
|
||||
return@put DoubleValue.ZERO
|
||||
}
|
||||
}
|
||||
map["is_battling"] = {
|
||||
DoubleValue(player.isInBattle())
|
||||
}
|
||||
}
|
||||
|
||||
if (player is AbstractClientPlayer) {
|
||||
map["is_battling"] = {
|
||||
DoubleValue(CobblemonClient.battle?.spectating == false) // Checks not-null and not-spectating at the same time, trust
|
||||
}
|
||||
}
|
||||
|
||||
return map
|
||||
|
||||
+27
@@ -15,6 +15,7 @@ import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonMovesetBuilders
|
||||
import com.cobblemon.mod.common.CobblemonPokeSkills
|
||||
import com.cobblemon.mod.common.api.mark.Marks
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
|
||||
import com.cobblemon.mod.common.api.moves.BenchedMove
|
||||
@@ -26,6 +27,9 @@ import com.cobblemon.mod.common.api.riding.stats.RidingStat
|
||||
import com.cobblemon.mod.common.api.storage.party.PartyStore
|
||||
import com.cobblemon.mod.common.pokemon.IVs
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.pokemon.activestate.ActivePokemonState
|
||||
import com.cobblemon.mod.common.pokemon.activestate.SentOutState
|
||||
import com.cobblemon.mod.common.pokemon.activestate.ShoulderedState
|
||||
import com.cobblemon.mod.common.util.asArrayValue
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.cobblemon.mod.common.util.getBooleanOrNull
|
||||
@@ -447,6 +451,29 @@ object PokemonMoLangFunctions : AbstractMoLangFunctionHolder<Pokemon>() {
|
||||
evolution?.forceEvolve(pokemon)
|
||||
StringValue(evolution.toString())
|
||||
}
|
||||
map["is_sent_out"] = {
|
||||
DoubleValue(pokemon.state is SentOutState)
|
||||
}
|
||||
map["is_shouldered"] = {
|
||||
DoubleValue(pokemon.state is ShoulderedState)
|
||||
}
|
||||
map["entity"] = {
|
||||
(pokemon.state as? ActivePokemonState)?.entity?.struct ?: DoubleValue.ZERO
|
||||
}
|
||||
map["is_rideable"] = put@{
|
||||
return@put DoubleValue(!pokemon.riding.behaviours.isNullOrEmpty())
|
||||
}
|
||||
map["has_status"] = put@{ params ->
|
||||
val status = params.getString(0).asIdentifierDefaultingNamespace()
|
||||
return@put DoubleValue(pokemon.status?.status?.name == status)
|
||||
}
|
||||
map["add_skill_cooldown"] = put@{ params ->
|
||||
val skillId = params.getString(0).asIdentifierDefaultingNamespace()
|
||||
val cooldownTicks = params.getIntOrNull(1)
|
||||
val skill = CobblemonPokeSkills.skills[skillId] ?: return@put DoubleValue.ZERO
|
||||
pokemon.addSkillCooldown(skillId, cooldownTicks ?: skill.cooldownTicks)
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
|
||||
map["entity"] = { pokemon.entity?.asMoLangValue() ?: DoubleValue.ZERO }
|
||||
map["is_alpha"] = { DoubleValue(pokemon.isAlpha) }
|
||||
|
||||
+23
-2
@@ -40,6 +40,7 @@ import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.Level.ExplosionInteraction
|
||||
import net.minecraft.world.level.biome.Biome
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.entity.AbstractFurnaceBlockEntity
|
||||
import net.minecraft.world.level.levelgen.Heightmap
|
||||
import net.minecraft.world.level.storage.loot.LootParams
|
||||
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets
|
||||
@@ -61,6 +62,26 @@ object WorldMoLangFunctions : AbstractMoLangFunctionHolder<Holder<Level>>() {
|
||||
val time = world.dayTime % 24000
|
||||
return@put DoubleValue(timeOfDay.contains(time.toInt()))
|
||||
}
|
||||
map["add_furnace_fuel"] = put@{ params ->
|
||||
val x = params.getInt(0)
|
||||
val y = params.getInt(1)
|
||||
val z = params.getInt(2)
|
||||
val fuelTicks = params.getInt(3)
|
||||
|
||||
val blockEntity = world.getBlockEntity(BlockPos(x, y, z))
|
||||
if (blockEntity is AbstractFurnaceBlockEntity) {
|
||||
// Add fuel time to the furnace
|
||||
blockEntity.litTime += fuelTicks
|
||||
|
||||
// If this exceeds the litDuration then bump it up
|
||||
if (blockEntity.litTime >= blockEntity.litDuration) {
|
||||
blockEntity.litDuration = blockEntity.litTime
|
||||
}
|
||||
blockEntity.setChanged()
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
return@put DoubleValue.ZERO
|
||||
}
|
||||
map["game_time"] = { _ -> DoubleValue(world.gameTime.toDouble()) }
|
||||
map["time_of_day"] = put@{
|
||||
val time = world.dayTime % 24000
|
||||
@@ -128,13 +149,13 @@ object WorldMoLangFunctions : AbstractMoLangFunctionHolder<Holder<Level>>() {
|
||||
val x = params.getDouble(0)
|
||||
val y = params.getDouble(1)
|
||||
val z = params.getDouble(2)
|
||||
val range = params.getDouble(3).toFloat()
|
||||
val range = params.getDoubleOrNull(3) ?: 8.0
|
||||
world.explode(
|
||||
null,
|
||||
x,
|
||||
y,
|
||||
z,
|
||||
range,
|
||||
range.toFloat(),
|
||||
ExplosionInteraction.valueOf(
|
||||
params.getStringOrNull(4)?.uppercase() ?: ExplosionInteraction.TNT.name
|
||||
)
|
||||
|
||||
+2
-1
@@ -50,7 +50,7 @@ class ActionEffectTimeline(
|
||||
}
|
||||
|
||||
fun chainKeyframes(context: ActionEffectContext, iterator: Iterator<ActionEffectKeyframe>, finalFuture: CompletableFuture<Unit>) {
|
||||
if (!iterator.hasNext()) {
|
||||
if (!iterator.hasNext() || context.cancelled) {
|
||||
finalFuture.complete(Unit)
|
||||
} else {
|
||||
val keyframe = iterator.next()
|
||||
@@ -70,6 +70,7 @@ class ActionEffectContext(
|
||||
val runtime: MoLangRuntime,
|
||||
var canBeInterrupted: Boolean = false,
|
||||
var interrupted: Boolean = false,
|
||||
var cancelled: Boolean = false,
|
||||
var currentKeyframes: MutableList<ActionEffectKeyframe> = mutableListOf(),
|
||||
var level: Level? = null
|
||||
) {
|
||||
|
||||
@@ -57,6 +57,7 @@ object ActionEffects : JsonDataRegistry<ActionEffectTimeline> {
|
||||
ActionEffectKeyframe.register<RunActionEffectKeyframe>("run_action_effect")
|
||||
ActionEffectKeyframe.register<EntityParticlesActionEffectKeyframe>("entity_particles")
|
||||
ActionEffectKeyframe.register<EntitySoundActionEffectKeyframe>("entity_sound")
|
||||
ActionEffectKeyframe.register<CancelActionEffectKeyframe>("cancel")
|
||||
}
|
||||
|
||||
override val gson = GsonBuilder()
|
||||
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.moves.animations.keyframes
|
||||
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import java.util.concurrent.CompletableFuture
|
||||
|
||||
class CancelActionEffectKeyframe : ConditionalActionEffectKeyframe() {
|
||||
override fun playWhenTrue(context: ActionEffectContext): CompletableFuture<Unit> {
|
||||
context.cancelled = true
|
||||
return CompletableFuture.completedFuture(Unit)
|
||||
}
|
||||
}
|
||||
+28
-6
@@ -21,6 +21,7 @@ import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import net.minecraft.commands.arguments.EntityArgument.getPlayers
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
/**
|
||||
* Spawns particles on the entity based on the given particle effect and locator.
|
||||
@@ -65,15 +66,36 @@ class EntityParticlesActionEffectKeyframe : ConditionalActionEffectKeyframe(), E
|
||||
allEntities.any { player.distanceTo(it) <= visibilityRange }
|
||||
}
|
||||
|
||||
// Try to resolve a world-position target from runtime variables
|
||||
val runtimeTargetPosition: Vec3? = try {
|
||||
val x = "v.target_x".asExpressionLike().resolveDouble(context.runtime)
|
||||
val y = "v.target_y".asExpressionLike().resolveDouble(context.runtime)
|
||||
val z = "v.target_z".asExpressionLike().resolveDouble(context.runtime)
|
||||
if (x != 0.0 || y != 0.0 || z != 0.0) Vec3(x, y, z) else null
|
||||
} catch (e: Exception) {
|
||||
null
|
||||
}
|
||||
|
||||
|
||||
sourceEntities.filter { it is PosableEntity }.forEach { entity ->
|
||||
if (targetLocators == null) {
|
||||
val packet = SpawnSnowstormEntityParticlePacket(effectIdentifier, entity.id, locators)
|
||||
packet.sendToPlayers(players)
|
||||
}
|
||||
else {
|
||||
// If target entities are specified, send the particle using entity locators/position.
|
||||
// If there are no target entities then attempt to send to v.target world position or send without target.
|
||||
if (targetEntities.isNotEmpty()) {
|
||||
targetEntities.forEach { targetEntity ->
|
||||
val packet = SpawnSnowstormEntityParticlePacket(effectIdentifier, entity.id, locators, targetEntity.id, targetLocators!!.toList())
|
||||
if (targetLocators != null) {
|
||||
val packet = SpawnSnowstormEntityParticlePacket(effectIdentifier, entity.id, locators, targetEntity.id, targetLocators!!.toList())
|
||||
packet.sendToPlayers(players)
|
||||
} else {
|
||||
val packet = SpawnSnowstormEntityParticlePacket(effectIdentifier, entity.id, locators, targetEntity.id)
|
||||
packet.sendToPlayers(players)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (runtimeTargetPosition != null) {
|
||||
val packet = SpawnSnowstormEntityParticlePacket(effectIdentifier, entity.id, locators, targetPosition = runtimeTargetPosition)
|
||||
packet.sendToPlayers(players)
|
||||
} else {
|
||||
val packet = SpawnSnowstormEntityParticlePacket(effectIdentifier, entity.id, locators)
|
||||
packet.sendToPlayers(players)
|
||||
}
|
||||
}
|
||||
|
||||
-2
@@ -8,8 +8,6 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.moves.animations.keyframes
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import com.cobblemon.mod.common.api.scheduling.delayedFuture
|
||||
|
||||
+25
-2
@@ -8,6 +8,8 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.moves.animations.keyframes
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffects
|
||||
import java.util.concurrent.CompletableFuture
|
||||
@@ -18,16 +20,37 @@ import net.minecraft.resources.ResourceLocation
|
||||
* effect is marked complete only when the action effect it runs is complete unless [waitForActionEffect] is
|
||||
* false.
|
||||
*
|
||||
* If [expression] is set, it will be resolved at runtime to determine the action effect identifier.
|
||||
* This allows dynamic delegation based on MoLang variables (e.g. v.granting_move).
|
||||
* If [expression] is not set, the static [actionEffect] identifier is used instead.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since January 21st, 2024
|
||||
*/
|
||||
class RunActionEffectKeyframe : ConditionalActionEffectKeyframe() {
|
||||
val actionEffect: ResourceLocation? = null
|
||||
val expression: ExpressionLike? = null
|
||||
val waitForActionEffect = true
|
||||
override fun playWhenTrue(context: ActionEffectContext): CompletableFuture<Unit> {
|
||||
return if (actionEffect != null) {
|
||||
ActionEffects.actionEffects[actionEffect]?.run(context)?.takeIf { waitForActionEffect } ?: skip()
|
||||
val effectId = if (expression != null) {
|
||||
val resolved = expression.resolveString(context.runtime)
|
||||
if (resolved == "0" || resolved.isBlank()) {
|
||||
Cobblemon.LOGGER.warn("RunActionEffectKeyframe expression resolved to empty/zero string: $resolved")
|
||||
return skip()
|
||||
}
|
||||
try {
|
||||
ResourceLocation.parse(resolved)
|
||||
} catch (e: Exception) {
|
||||
Cobblemon.LOGGER.warn("RunActionEffectKeyframe expression resolved to invalid resource location: $resolved with exception: $e")
|
||||
return skip()
|
||||
}
|
||||
} else {
|
||||
actionEffect
|
||||
}
|
||||
return if (effectId != null) {
|
||||
ActionEffects.actionEffects[effectId]?.run(context)?.takeIf { waitForActionEffect } ?: skip()
|
||||
} else {
|
||||
Cobblemon.LOGGER.warn("RunActionEffectKeyframe has no action effect identifier or expression to run")
|
||||
skip()
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -102,7 +102,7 @@ open class PlayerPartyStore(
|
||||
for (pokemon in this) {
|
||||
// Awake from fainted
|
||||
if (pokemon.isFainted()) {
|
||||
//Skip awaken logic check if config value is 0
|
||||
// Skip awaken logic check if config value is 0
|
||||
if (Cobblemon.config.faintAwakenHealthPercent > 0) {
|
||||
pokemon.faintedTimer -= 1
|
||||
if (pokemon.faintedTimer <= -1) {
|
||||
@@ -119,7 +119,7 @@ open class PlayerPartyStore(
|
||||
}
|
||||
// Passive healing while less than full health
|
||||
else if (pokemon.currentHealth < pokemon.maxHealth) {
|
||||
//Skip passive healing logic check if config value is 0
|
||||
// Skip passive healing logic check if config value is 0
|
||||
if (Cobblemon.config.healPercent > 0) {
|
||||
pokemon.healTimer--
|
||||
if (pokemon.healTimer <= -1) {
|
||||
|
||||
@@ -349,12 +349,11 @@ object BattleBuilder {
|
||||
npcPartyStores.add(npcParty)
|
||||
}
|
||||
|
||||
val playerAvailablePokemon = playerActor.pokemonList.count { it.health > 0 }
|
||||
if (playerAvailablePokemon < battleFormat.battleType.slotsPerActor) {
|
||||
if (playerActor.pokemonList.size < battleFormat.battleType.slotsPerActor) {
|
||||
errors.participantErrors[playerActor] += BattleStartError.insufficientPokemon(
|
||||
actorEntity = player,
|
||||
requiredCount = battleFormat.battleType.slotsPerActor,
|
||||
hadCount = playerAvailablePokemon
|
||||
hadCount = playerActor.pokemonList.size
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+2
-4
@@ -163,8 +163,7 @@ class TrackerActor(val uuid: UUID) {
|
||||
//we assume that AI knows it all about our allies
|
||||
trackerActor.party.addAll(actor.pokemonList.map { createAllied(it) })
|
||||
actor.activePokemon.forEach {
|
||||
val battlePokemon = it.battlePokemon ?: return@forEach
|
||||
val active = trackerActor.party.first { trackMon -> trackMon.id == battlePokemon.uuid }
|
||||
val active = trackerActor.party.first { trackMon -> trackMon.id == it.battlePokemon!!.uuid }
|
||||
trackerActor.party.remove(active)
|
||||
trackerActor.activePokemon.add(active)
|
||||
}
|
||||
@@ -177,8 +176,7 @@ class TrackerActor(val uuid: UUID) {
|
||||
//only know basics of what we see right now
|
||||
trackerActor.party.addAll(actor.pokemonList.map { createOpposing(it) })
|
||||
actor.activePokemon.forEach {
|
||||
val battlePokemon = it.battlePokemon ?: return@forEach
|
||||
val active = trackerActor.party.first { trackMon -> trackMon.id == battlePokemon.uuid }
|
||||
val active = trackerActor.party.first { trackMon -> trackMon.id == it.battlePokemon!!.uuid }
|
||||
trackerActor.party.remove(active)
|
||||
trackerActor.activePokemon.add(active)
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.block
|
||||
|
||||
//import dev.lambdaurora.lambdynlights.util.SodiumDynamicLightHandler.pos
|
||||
import com.cobblemon.mod.common.CobblemonBlockEntities
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.berry.Berries
|
||||
import com.cobblemon.mod.common.api.berry.Berry
|
||||
@@ -39,11 +40,7 @@ import net.minecraft.world.level.BlockGetter
|
||||
import net.minecraft.world.level.Level
|
||||
import net.minecraft.world.level.LevelAccessor
|
||||
import net.minecraft.world.level.LevelReader
|
||||
import net.minecraft.world.level.block.BaseEntityBlock
|
||||
import net.minecraft.world.level.block.Block
|
||||
import net.minecraft.world.level.block.Blocks
|
||||
import net.minecraft.world.level.block.BonemealableBlock
|
||||
import net.minecraft.world.level.block.RenderShape
|
||||
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
|
||||
@@ -131,10 +128,7 @@ class BerryBlock(private val berryIdentifier: ResourceLocation, settings: Proper
|
||||
val newAge = curAge + 1
|
||||
if (newAge > FRUIT_AGE) return
|
||||
val newState = state.setValue(AGE, newAge)
|
||||
val treeEntity = world.getBlockEntity(pos) as? BerryBlockEntity ?: run {
|
||||
world.setBlock(pos, Blocks.AIR.defaultBlockState(), UPDATE_CLIENTS)
|
||||
return
|
||||
}
|
||||
val treeEntity = world.getBlockEntity(pos) as BerryBlockEntity
|
||||
if (curAge == MATURE_AGE) {
|
||||
treeEntity.generateGrowthPoints(world, newState, pos, null)
|
||||
determineMutation(world, random, pos, newState)
|
||||
|
||||
@@ -60,12 +60,10 @@ class HabitatBlockEntity(pos: BlockPos, state: BlockState) :
|
||||
|
||||
var spawningStyle: HabitatSpawningStyle = ActivatedHabitatSpawning(this)
|
||||
|
||||
var numberOfPhases: Int = 1
|
||||
var phaseOrder = HabitatPhaseOrder.SIMPLE
|
||||
var currentPhase = 1
|
||||
|
||||
val numberOfPhases: Int
|
||||
get() = pool.getPhaseCount()
|
||||
|
||||
var levelRange: IntRange = 1..Cobblemon.config.maxPokemonLevel
|
||||
var modifiers: PokemonProperties = PokemonProperties()
|
||||
var pool: HabitatPool = HabitatPool.default()
|
||||
@@ -141,6 +139,7 @@ class HabitatBlockEntity(pos: BlockPos, state: BlockState) :
|
||||
val activatedSettings = habitatSettingsDTO.activatedSettings
|
||||
val naturalSettings = habitatSettingsDTO.naturalSettings
|
||||
val isActivated = habitatSettingsDTO.isActivatedSpawning
|
||||
this.numberOfPhases = habitatSettingsDTO.numberOfPhases
|
||||
this.phaseOrder = habitatSettingsDTO.phaseOrder
|
||||
this.levelRange = habitatSettingsDTO.levelRange
|
||||
this.modifiers = PokemonProperties.parse(habitatSettingsDTO.modifiers)
|
||||
@@ -170,6 +169,7 @@ class HabitatBlockEntity(pos: BlockPos, state: BlockState) :
|
||||
override fun saveAdditional(tag: CompoundTag, registryLookup: HolderLookup.Provider) {
|
||||
super.saveAdditional(tag, registryLookup)
|
||||
tag.putString(DataKeys.HABITAT_MIMIC, mimicId.toString())
|
||||
tag.putInt(DataKeys.HABITAT_PHASE_COUNT, numberOfPhases)
|
||||
tag.putString(DataKeys.HABITAT_PHASE_ORDER, phaseOrder.toString())
|
||||
// Only save the level range when it's a non-trivial one
|
||||
if (levelRange.first != 1 || levelRange.last != Cobblemon.config.maxPokemonLevel) {
|
||||
@@ -201,6 +201,7 @@ class HabitatBlockEntity(pos: BlockPos, state: BlockState) :
|
||||
return // Client doesn't need to try loading the rest
|
||||
}
|
||||
|
||||
numberOfPhases = tag.getInt(DataKeys.HABITAT_PHASE_COUNT)
|
||||
phaseOrder = HabitatPhaseOrder.valueOf(tag.getString(DataKeys.HABITAT_PHASE_ORDER))
|
||||
levelRange = tag.getString(DataKeys.HABITAT_LEVEL_RANGE).takeIf { it.isNotBlank() }?.let(IntRangeAdapter::deserialize) ?: 1..Cobblemon.config.maxPokemonLevel
|
||||
modifiers = tag.getString(DataKeys.HABITAT_MODIFIERS).takeIf { it.isNotBlank() }?.let(PokemonProperties::parse) ?: PokemonProperties()
|
||||
|
||||
@@ -10,13 +10,11 @@ package com.cobblemon.mod.common.block.tmmachine
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.CobblemonMenuType
|
||||
import com.cobblemon.mod.common.CobblemonNetwork.sendPacket
|
||||
import com.cobblemon.mod.common.api.moves.Moves
|
||||
import com.cobblemon.mod.common.api.tms.TechnicalMachine
|
||||
import com.cobblemon.mod.common.api.tms.TechnicalMachines
|
||||
import com.cobblemon.mod.common.block.entity.TMMachineBlockEntity
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.SynchronizeActiveTMPacket
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import com.cobblemon.mod.common.util.itemRegistry
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.util.Mth
|
||||
import net.minecraft.world.Container
|
||||
import net.minecraft.world.SimpleContainer
|
||||
@@ -37,45 +35,15 @@ class TMMachineMenu(menuType: MenuType<*>, syncId: Int) : AbstractContainerMenu(
|
||||
var inventory: Container? = null
|
||||
var containerData: ContainerData? = null
|
||||
|
||||
var currentlySelectedTM: TechnicalMachine? = null
|
||||
private var lastSelectedTM: TechnicalMachine? = null
|
||||
|
||||
var onSelectedTMUpdate: (TechnicalMachine?) -> Unit = {}
|
||||
|
||||
constructor(syncId: Int, playerInventory: Inventory) : this(CobblemonMenuType.TM_MACHINE, syncId) {
|
||||
this.playerInventory = playerInventory
|
||||
this.inventory = SimpleContainer(5)
|
||||
this.containerData = SimpleContainerData(6)
|
||||
this.tmMachineEntity = (inventory as? TMMachineBlockEntity.TMMachineBlockInventory)?.blockEntity
|
||||
|
||||
this.addDataSlots(containerData!!)
|
||||
inventory?.startOpen(playerInventory.player)
|
||||
|
||||
initiateSlots()
|
||||
}
|
||||
|
||||
constructor(syncId: Int, playerInventory: Inventory, inventory: Container, containerData: ContainerData) : this(CobblemonMenuType.TM_MACHINE, syncId) {
|
||||
this.playerInventory = playerInventory
|
||||
this.inventory = inventory
|
||||
this.containerData = containerData
|
||||
this.tmMachineEntity = (inventory as? TMMachineBlockEntity.TMMachineBlockInventory)?.blockEntity
|
||||
|
||||
this.addDataSlots(containerData)
|
||||
inventory.startOpen(playerInventory.player)
|
||||
|
||||
initiateSlots()
|
||||
|
||||
tmMachineEntity?.let {
|
||||
val move = Moves.getByName(it.activeMove)
|
||||
move.let {
|
||||
currentlySelectedTM = TechnicalMachines.moveToTM[it]
|
||||
synchronizeSelectedTM()
|
||||
}
|
||||
}
|
||||
|
||||
this.addSlotListener(this)
|
||||
}
|
||||
|
||||
private fun initiateSlots() {
|
||||
val startX = 15
|
||||
val startY = 144
|
||||
val slotWidth = 18
|
||||
@@ -90,7 +58,41 @@ class TMMachineMenu(menuType: MenuType<*>, syncId: Int) : AbstractContainerMenu(
|
||||
this.addSlot(Slot(playerInventory, col, startX + (slotWidth * col), startY + 58))
|
||||
}
|
||||
|
||||
val container = inventory!!
|
||||
val container = inventory
|
||||
container?.let {
|
||||
this.addSlot(TMResultSlot(container, RESULT_SLOT, startX + 37, startY - 28)) // Output slot
|
||||
this.addSlot(BlankTMSlot(container, BLANK_TM_SLOT, startX + 90, startY - 28)) // Blank TM
|
||||
for (index in INGREDIENT_SLOTS) {
|
||||
this.addSlot(Slot(container, index, startX + 114 + (18 * (index - INGREDIENT_SLOTS.first)), startY - 28))
|
||||
}
|
||||
}
|
||||
this.addSlotListener(this)
|
||||
}
|
||||
|
||||
constructor(syncId: Int, playerInventory: Inventory, inventory: Container, containerData: ContainerData) : this(CobblemonMenuType.TM_MACHINE, syncId) {
|
||||
this.playerInventory = playerInventory
|
||||
this.inventory = inventory
|
||||
this.containerData = containerData
|
||||
this.tmMachineEntity = (inventory as? TMMachineBlockEntity.TMMachineBlockInventory)?.blockEntity
|
||||
|
||||
this.addDataSlots(containerData)
|
||||
inventory.startOpen(playerInventory.player)
|
||||
|
||||
val startX = 15
|
||||
val startY = 144
|
||||
val slotWidth = 18
|
||||
val slotHeight = 18
|
||||
|
||||
for (row in 0..2) {
|
||||
for (col in 0..8) {
|
||||
this.addSlot(Slot(playerInventory, 9 + (row * 9) + col, startX + (slotWidth * col), startY + (slotHeight * row)))
|
||||
}
|
||||
}
|
||||
for (col in 0..8) {
|
||||
this.addSlot(Slot(playerInventory, col, startX + (slotWidth * col), startY + 58))
|
||||
}
|
||||
|
||||
val container = inventory
|
||||
container.let {
|
||||
this.addSlot(TMResultSlot(container, RESULT_SLOT, startX + 37, startY - 28)) // Output slot
|
||||
this.addSlot(BlankTMSlot(container, BLANK_TM_SLOT, startX + 90, startY - 28)) // Blank TM
|
||||
@@ -98,6 +100,7 @@ class TMMachineMenu(menuType: MenuType<*>, syncId: Int) : AbstractContainerMenu(
|
||||
this.addSlot(Slot(container, index, startX + 114 + (18 * (index - INGREDIENT_SLOTS.first)), startY - 28))
|
||||
}
|
||||
}
|
||||
this.addSlotListener(this)
|
||||
}
|
||||
|
||||
override fun quickMoveStack(player: Player, index: Int): ItemStack {
|
||||
@@ -204,25 +207,4 @@ class TMMachineMenu(menuType: MenuType<*>, syncId: Int) : AbstractContainerMenu(
|
||||
override fun dataChanged(containerMenu: AbstractContainerMenu, dataSlotIndex: Int, value: Int) {
|
||||
broadcastChanges()
|
||||
}
|
||||
|
||||
fun synchronizeSelectedTM() {
|
||||
val serverPlayer = playerInventory?.player as? ServerPlayer ?: return
|
||||
serverPlayer.sendPacket(SynchronizeActiveTMPacket(currentlySelectedTM))
|
||||
lastSelectedTM = currentlySelectedTM
|
||||
}
|
||||
|
||||
override fun sendAllDataToRemote() {
|
||||
super.sendAllDataToRemote()
|
||||
synchronizeSelectedTM()
|
||||
}
|
||||
|
||||
override fun broadcastChanges() {
|
||||
super.broadcastChanges()
|
||||
if (lastSelectedTM != currentlySelectedTM) synchronizeSelectedTM()
|
||||
}
|
||||
|
||||
fun clientSetSelectedTM(tm: TechnicalMachine?) {
|
||||
currentlySelectedTM = tm
|
||||
onSelectedTMUpdate(tm)
|
||||
}
|
||||
}
|
||||
@@ -179,6 +179,8 @@ object CobblemonClient {
|
||||
return@subscribe
|
||||
}
|
||||
|
||||
storage.party.forEach { it?.tickSkillCooldowns() }
|
||||
|
||||
val nearbyPokemon = player.level().getEntities(
|
||||
player,
|
||||
AABB.ofSize(player.position(), 16.0, 16.0, 16.0)
|
||||
|
||||
@@ -49,7 +49,7 @@ object MountedCameraTypeHandler {
|
||||
return
|
||||
}
|
||||
val currentCameraType = mc.options.cameraType
|
||||
if (Cobblemon.config.rememberRidingCamera && currentCameraType != unmountedCameraType) {
|
||||
if (currentCameraType != unmountedCameraType) {
|
||||
mc.options.cameraType = unmountedCameraType
|
||||
}
|
||||
val data = ClientPersistedData.ridingPerspectives
|
||||
|
||||
@@ -27,18 +27,10 @@ import net.minecraft.client.renderer.RenderType
|
||||
import net.minecraft.client.renderer.texture.OverlayTexture
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.Mth
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import org.joml.Quaternionf
|
||||
import org.joml.Vector3f
|
||||
import kotlin.math.atan
|
||||
|
||||
enum class ProfileTransformType {
|
||||
PROFILE,
|
||||
NONE,
|
||||
POKEDEX,
|
||||
SUMMARY,
|
||||
}
|
||||
|
||||
fun drawProfilePokemon(
|
||||
renderablePokemon: RenderablePokemon,
|
||||
matrixStack: PoseStack,
|
||||
@@ -47,7 +39,7 @@ fun drawProfilePokemon(
|
||||
state: PosableState,
|
||||
partialTicks: Float,
|
||||
scale: Float = 20F,
|
||||
profileTransformType: ProfileTransformType = ProfileTransformType.PROFILE,
|
||||
applyProfileTransform: Boolean = true,
|
||||
applyBaseScale: Boolean = false,
|
||||
r: Float = 1F,
|
||||
g: Float = 1F,
|
||||
@@ -64,7 +56,7 @@ fun drawProfilePokemon(
|
||||
state = state.also { it.currentAspects = renderablePokemon.aspects },
|
||||
partialTicks = partialTicks,
|
||||
scale = scale,
|
||||
profileTransformType = profileTransformType,
|
||||
applyProfileTransform = applyProfileTransform,
|
||||
applyBaseScale = applyBaseScale,
|
||||
r = r,
|
||||
g = g,
|
||||
@@ -83,7 +75,7 @@ fun drawProfilePokemon(
|
||||
state: PosableState,
|
||||
partialTicks: Float,
|
||||
scale: Float = 20F,
|
||||
profileTransformType: ProfileTransformType = ProfileTransformType.PROFILE,
|
||||
applyProfileTransform: Boolean = true,
|
||||
applyBaseScale: Boolean = false,
|
||||
doQuirks: Boolean = false,
|
||||
r: Float = 1F,
|
||||
@@ -122,38 +114,18 @@ fun drawProfilePokemon(
|
||||
state.setPoseToFirstSuitable(poseType)
|
||||
state.updatePartialTicks(partialTicks)
|
||||
|
||||
if (profileTransformType == ProfileTransformType.NONE) {
|
||||
if (applyProfileTransform) {
|
||||
matrixStack.translate(
|
||||
model.profileTranslation.x,
|
||||
model.profileTranslation.y + 1.5 * model.profileScale,
|
||||
model.profileTranslation.z - 4.0
|
||||
)
|
||||
matrixStack.scale(model.profileScale, model.profileScale, 1 / model.profileScale)} else {
|
||||
matrixStack.translate(0F, 0F, -4.0F)
|
||||
if (applyBaseScale) {
|
||||
matrixStack.scale(baseScale, baseScale, 1 / baseScale)
|
||||
}
|
||||
} else {
|
||||
var profileScale: Float
|
||||
var profileTranslation: Vec3
|
||||
|
||||
when (profileTransformType) {
|
||||
ProfileTransformType.POKEDEX -> {
|
||||
profileScale = model.profilePokedexScale ?: model.profileScale
|
||||
profileTranslation = model.profilePokedexTranslation ?: model.profileTranslation
|
||||
}
|
||||
ProfileTransformType.SUMMARY -> {
|
||||
profileScale = model.profileSummaryScale ?: model.profileScale
|
||||
profileTranslation = model.profileSummaryTranslation ?: model.profileTranslation
|
||||
}
|
||||
else -> {
|
||||
profileScale = model.profileScale
|
||||
profileTranslation = model.profileTranslation
|
||||
}
|
||||
}
|
||||
|
||||
matrixStack.translate(
|
||||
profileTranslation.x,
|
||||
profileTranslation.y + 1.5 * profileScale,
|
||||
profileTranslation.z - 4.0
|
||||
)
|
||||
matrixStack.scale(profileScale, profileScale, 1 / profileScale)
|
||||
}
|
||||
|
||||
matrixStack.mulPose(rotation)
|
||||
|
||||
model.applyAnimations(null, state, 0F, 0F, 0F, headYaw, headPitch)
|
||||
|
||||
@@ -1,97 +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.gui
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.FloatingState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
|
||||
import com.mojang.blaze3d.platform.InputConstants
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
fun handleProfileDebugKeys(keyCode: Int, poserResourceLocation: ResourceLocation, state: FloatingState) {
|
||||
if (!Cobblemon.config.enableDebugKeys) {
|
||||
return
|
||||
}
|
||||
val model = VaryingModelRepository.getPoser(poserResourceLocation, state)
|
||||
|
||||
val delta = when (keyCode) {
|
||||
InputConstants.KEY_UP -> Vec3(0.0, -0.01, 0.0)
|
||||
InputConstants.KEY_DOWN -> Vec3(0.0, 0.01, 0.0)
|
||||
InputConstants.KEY_LEFT -> Vec3(-0.01, 0.0, 0.0)
|
||||
InputConstants.KEY_RIGHT -> Vec3(0.01, 0.0, 0.0)
|
||||
else -> null
|
||||
}
|
||||
|
||||
if (delta != null) {
|
||||
model.profileTranslation = model.profileTranslation.add(delta)
|
||||
model.profileSummaryTranslation = model.profileSummaryTranslation?.add(delta)
|
||||
model.profilePokedexTranslation = model.profilePokedexTranslation?.add(delta)
|
||||
}
|
||||
|
||||
val scaleDelta = when (keyCode) {
|
||||
InputConstants.KEY_EQUALS -> 0.01F
|
||||
InputConstants.KEY_MINUS -> -0.01F
|
||||
else -> null
|
||||
}
|
||||
|
||||
if (scaleDelta != null) {
|
||||
model.profileScale += scaleDelta
|
||||
model.profileSummaryScale = model.profileSummaryScale?.plus(scaleDelta)
|
||||
model.profilePokedexScale = model.profilePokedexScale?.plus(scaleDelta)
|
||||
}
|
||||
}
|
||||
|
||||
fun logProfileTranslations(poserResourceLocation: ResourceLocation, state: FloatingState) {
|
||||
if (!Cobblemon.config.enableDebugKeys) {
|
||||
return
|
||||
}
|
||||
|
||||
val model = VaryingModelRepository.getPoser(poserResourceLocation, state)
|
||||
val player = Minecraft.getInstance().player
|
||||
|
||||
fun Double.f2() = "%.2f".format(this)
|
||||
fun Float.f2() = "%.2f".format(this)
|
||||
|
||||
fun sendTranslation(name: String, translation: Vec3) {
|
||||
player?.sendSystemMessage(Component.literal("$name Translation: (${translation.x.f2()}, ${translation.y.f2()}, ${translation.z.f2()})"))
|
||||
}
|
||||
|
||||
fun sendScale(name: String, scale: Float) {
|
||||
player?.sendSystemMessage(Component.literal("$name Scale: ${scale.f2()}"))
|
||||
}
|
||||
|
||||
fun logTranslation(name: String, translation: Vec3) {
|
||||
Cobblemon.LOGGER.info("override var ${name.replaceFirstChar(Char::lowercase)}Translation = Vec3(${translation.x.f2()}, ${translation.y.f2()}, ${translation.z.f2()})")
|
||||
}
|
||||
|
||||
fun logScale(name: String, scale: Float) {
|
||||
Cobblemon.LOGGER.info("override var ${name.replaceFirstChar(Char::lowercase)}Scale = ${scale.f2()}F")
|
||||
}
|
||||
|
||||
sendTranslation("Profile", model.profileTranslation)
|
||||
sendScale("Profile", model.profileScale)
|
||||
|
||||
model.profileSummaryTranslation?.let { sendTranslation("Summary Profile", it) }
|
||||
model.profileSummaryScale?.let { sendScale("Summary Profile", it) }
|
||||
|
||||
model.profilePokedexTranslation?.let { sendTranslation("Pokedex Profile", it) }
|
||||
model.profilePokedexScale?.let { sendScale("Pokedex Profile", it) }
|
||||
|
||||
logTranslation("Profile", model.profileTranslation)
|
||||
logScale("Profile", model.profileScale)
|
||||
|
||||
model.profileSummaryTranslation?.let { logTranslation("ProfileSummary", it) }
|
||||
model.profileSummaryScale?.let { logScale("ProfileSummary", it) }
|
||||
|
||||
model.profilePokedexTranslation?.let { logTranslation("ProfilePokedex", it) }
|
||||
model.profilePokedexScale?.let { logScale("ProfilePokedex", it) }
|
||||
}
|
||||
+29
-18
@@ -115,19 +115,35 @@ class HabitatEditGUI(
|
||||
addOptionWidget(mimicInput)
|
||||
y += spacing
|
||||
|
||||
// Phase setting only visible if there's more than one phase
|
||||
val phaseCount = habitatSettingsDTO.pool.toHabitatPool()?.getPhaseCount() ?: 1
|
||||
if (phaseCount > 1) {
|
||||
phaseOrderButton = addOptionWidget(
|
||||
Button.builder(getPhaseOrderText()) {
|
||||
val orders = HabitatPhaseOrder.entries
|
||||
val currentIndex = orders.indexOf(habitatSettingsDTO.phaseOrder)
|
||||
habitatSettingsDTO.phaseOrder = orders[(currentIndex + 1) % orders.size]
|
||||
refresh()
|
||||
}.bounds(10, y, buttonWidth, 20).build()
|
||||
)
|
||||
y += spacing
|
||||
labels.add(lang("ui.edit.habitat.phase_number") to (10 to y))
|
||||
y += 12
|
||||
val phasesInput = EditBox(font, 10, y, buttonWidth, 20, "Phases".text())
|
||||
phasesInput.value = habitatSettingsDTO.numberOfPhases.toString()
|
||||
phasesInput.setResponder { value ->
|
||||
val phases = value.toIntOrNull()
|
||||
val valid = phases != null && phases > 0
|
||||
if (valid) {
|
||||
habitatSettingsDTO.numberOfPhases = phases
|
||||
}
|
||||
phasesInput.setTextColor(if (valid) validTextColor else invalidTextColor)
|
||||
setFieldValidity("phases", valid, "ui.edit.habitat.validation.phases")
|
||||
}
|
||||
val initialPhases = phasesInput.value.toIntOrNull()
|
||||
val initialPhasesValid = initialPhases != null && initialPhases > 0
|
||||
phasesInput.setTextColor(if (initialPhasesValid) validTextColor else invalidTextColor)
|
||||
setFieldValidity("phases", initialPhasesValid, "ui.edit.habitat.validation.phases")
|
||||
addOptionWidget(phasesInput)
|
||||
y += spacing
|
||||
|
||||
phaseOrderButton = addOptionWidget(
|
||||
Button.builder(getPhaseOrderText()) {
|
||||
val orders = HabitatPhaseOrder.entries
|
||||
val currentIndex = orders.indexOf(habitatSettingsDTO.phaseOrder)
|
||||
habitatSettingsDTO.phaseOrder = orders[(currentIndex + 1) % orders.size]
|
||||
refresh()
|
||||
}.bounds(10, y, buttonWidth, 20).build()
|
||||
)
|
||||
y += spacing
|
||||
|
||||
labels.add(lang("ui.edit.habitat.level_range") to (10 to y))
|
||||
y += 12
|
||||
@@ -374,10 +390,7 @@ class HabitatEditGUI(
|
||||
}
|
||||
|
||||
fun refresh() {
|
||||
val phaseCount = habitatSettingsDTO.pool.toHabitatPool()?.getPhaseCount() ?: 1
|
||||
if (phaseCount > 1 && ::phaseOrderButton.isInitialized) {
|
||||
phaseOrderButton.message = getPhaseOrderText()
|
||||
}
|
||||
phaseOrderButton.message = getPhaseOrderText()
|
||||
spawnModeButton.message = getSpawnModeText()
|
||||
poolSelectorButton.message = getPoolText()
|
||||
viewPoolButton.message = getViewPoolText()
|
||||
@@ -426,7 +439,6 @@ class HabitatEditGUI(
|
||||
}
|
||||
habitatSettingsDTO.pool = newCustomPool
|
||||
}
|
||||
rebuildWidgets()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -439,7 +451,6 @@ class HabitatEditGUI(
|
||||
}
|
||||
|
||||
habitatSettingsDTO.pool = selectedPool
|
||||
rebuildWidgets()
|
||||
}
|
||||
|
||||
private fun validateLevelRangeInputs() {
|
||||
|
||||
+6
-4
@@ -45,6 +45,7 @@ class HabitatSpawnEditorGUI(
|
||||
private val actionButtonBottomMargin = 10
|
||||
private val validTextColor = 0xFFFFFF
|
||||
private val invalidTextColor = 0xFF5555
|
||||
private val moonPhaseRange = 0..7
|
||||
private lateinit var positionTypeButton: Button
|
||||
private lateinit var bucketButton: Button
|
||||
private lateinit var timeOfDayButton: Button
|
||||
@@ -184,7 +185,7 @@ class HabitatSpawnEditorGUI(
|
||||
phasesInput.setTextColor(validTextColor)
|
||||
setFieldValidity("phases_list", true, "ui.edit.habitat.validation.phases_list")
|
||||
} else {
|
||||
val parsed = parsePhases(value)
|
||||
val parsed = parseMoonPhases(value)
|
||||
val valid = parsed != null
|
||||
if (valid) {
|
||||
spawn.phases = parsed
|
||||
@@ -193,7 +194,7 @@ class HabitatSpawnEditorGUI(
|
||||
setFieldValidity("phases_list", valid, "ui.edit.habitat.validation.phases_list")
|
||||
}
|
||||
}
|
||||
val initialPhasesValid = phasesInput.value.isBlank() || parsePhases(phasesInput.value) != null
|
||||
val initialPhasesValid = phasesInput.value.isBlank() || parseMoonPhases(phasesInput.value) != null
|
||||
phasesInput.setTextColor(if (initialPhasesValid) validTextColor else invalidTextColor)
|
||||
setFieldValidity("phases_list", initialPhasesValid, "ui.edit.habitat.validation.phases_list")
|
||||
addOptionWidget(phasesInput)
|
||||
@@ -331,7 +332,7 @@ class HabitatSpawnEditorGUI(
|
||||
return runCatching { PokemonSpecies.getByName(lowered) }.getOrNull()
|
||||
}
|
||||
|
||||
private fun parsePhases(raw: String): IntRanges? {
|
||||
private fun parseMoonPhases(raw: String): IntRanges? {
|
||||
val ranges = mutableListOf<IntRange>()
|
||||
val tokens = raw.split(",").map(String::trim)
|
||||
if (tokens.isEmpty() || tokens.any { it.isEmpty() }) {
|
||||
@@ -343,12 +344,13 @@ class HabitatSpawnEditorGUI(
|
||||
val range = when (parts.size) {
|
||||
1 -> {
|
||||
val value = parts[0].toIntOrNull() ?: return null
|
||||
if (value !in moonPhaseRange) return null
|
||||
value..value
|
||||
}
|
||||
2 -> {
|
||||
val start = parts[0].toIntOrNull() ?: return null
|
||||
val end = parts[1].toIntOrNull() ?: return null
|
||||
if (start > end) {
|
||||
if (start !in moonPhaseRange || end !in moonPhaseRange || start > end) {
|
||||
return null
|
||||
}
|
||||
start..end
|
||||
|
||||
+6
-6
@@ -28,7 +28,7 @@ class InteractWheelButton(
|
||||
private val tooltipText: String?,
|
||||
x: Int,
|
||||
y: Int,
|
||||
private val isEnabled: Boolean,
|
||||
private val isEnabled: () -> Boolean,
|
||||
private val colour: () -> Vector3f?,
|
||||
onPress: OnPress,
|
||||
private val canHover: (Double, Double) -> Boolean
|
||||
@@ -74,12 +74,12 @@ class InteractWheelButton(
|
||||
y = y,
|
||||
width = width,
|
||||
height = height,
|
||||
vOffset = if (isHovered(mouseX.toFloat(), mouseY.toFloat()) && isEnabled) height else 0,
|
||||
vOffset = if (isHovered(mouseX.toFloat(), mouseY.toFloat()) && isEnabled()) height else 0,
|
||||
textureHeight = height * 2,
|
||||
alpha = if (isEnabled) 1f else 0.4F
|
||||
alpha = if (isEnabled()) 1f else 0.4F
|
||||
)
|
||||
|
||||
if(isEnabled && isHovered(mouseX.toFloat(), mouseY.toFloat())){
|
||||
if (isEnabled() && isHovered(mouseX.toFloat(), mouseY.toFloat())){
|
||||
tooltipText?.let {
|
||||
context.renderTooltip(Minecraft.getInstance().font, Component.translatable(it), mouseX, mouseY)
|
||||
}
|
||||
@@ -95,7 +95,7 @@ class InteractWheelButton(
|
||||
y = iconY,
|
||||
width = ICON_SIZE,
|
||||
height = ICON_SIZE,
|
||||
alpha = if (isEnabled) 1F else 0.2F,
|
||||
alpha = if (isEnabled()) 1F else 0.2F,
|
||||
red = colour.x,
|
||||
green = colour.y,
|
||||
blue = colour.z,
|
||||
@@ -114,7 +114,7 @@ class InteractWheelButton(
|
||||
y = iconY - ICON_SIZE,
|
||||
width = ICON_SIZE,
|
||||
height = ICON_SIZE,
|
||||
alpha = if (isEnabled) 1F else 0.4F,
|
||||
alpha = if (isEnabled()) 1F else 0.4F,
|
||||
red = colour.x,
|
||||
green = colour.y,
|
||||
blue = colour.z,
|
||||
|
||||
+3
-3
@@ -18,7 +18,7 @@ import net.minecraft.client.gui.screens.Screen
|
||||
import net.minecraft.network.chat.Component
|
||||
import kotlin.math.max
|
||||
|
||||
class InteractWheelGUI(private val options: Multimap<Orientation, InteractWheelOption>, title: Component) : Screen(title), CobblemonRenderable {
|
||||
open class InteractWheelGUI(private val options: Multimap<Orientation, InteractWheelOption>, title: Component) : Screen(title), CobblemonRenderable {
|
||||
companion object {
|
||||
const val SIZE = 170
|
||||
private val backgroundResource = cobblemonResource("textures/gui/interact/interact_wheel_base.png")
|
||||
@@ -32,7 +32,7 @@ class InteractWheelGUI(private val options: Multimap<Orientation, InteractWheelO
|
||||
return super.keyPressed(keyCode, scanCode, modifiers)
|
||||
}
|
||||
|
||||
private val buttons = mutableListOf<InteractWheelButton>()
|
||||
protected val buttons = mutableListOf<InteractWheelButton>()
|
||||
private var maxPage = 1
|
||||
private var currentPage = 0
|
||||
override fun renderBlurredBackground(delta: Float) { }
|
||||
@@ -104,7 +104,7 @@ class InteractWheelGUI(private val options: Multimap<Orientation, InteractWheelO
|
||||
tooltipText = option?.tooltipText,
|
||||
x = x,
|
||||
y = y,
|
||||
isEnabled = option != null && option.enabled,
|
||||
isEnabled = { option != null && option.enabled() },
|
||||
colour = option?.colour ?: { null },
|
||||
onPress = { option?.onPress?.invoke() },
|
||||
canHover = { a: Double, b: Double -> !isMouseInCenter(a, b)}
|
||||
|
||||
+37
-4
@@ -9,20 +9,24 @@
|
||||
package com.cobblemon.mod.common.client.gui.interact.wheel
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonNetwork
|
||||
import com.cobblemon.mod.common.CobblemonPokeSkills
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents
|
||||
import com.cobblemon.mod.common.api.events.pokemon.interaction.PokemonInteractionGUICreationEvent
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.gui.interact.battleRequest.BattleConfigureGUI
|
||||
import com.cobblemon.mod.common.net.messages.client.PlayerInteractOptionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.UsePokeSkillPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.battle.SpectateBattlePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.interact.InteractPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.AcceptTradeRequestPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.trade.OfferTradePacket
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.google.common.collect.ArrayListMultimap
|
||||
import com.google.common.collect.Multimap
|
||||
import java.util.UUID
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.player.AbstractClientPlayer
|
||||
import net.minecraft.network.chat.Component
|
||||
import org.joml.Vector3f
|
||||
|
||||
@@ -30,7 +34,7 @@ fun createPokemonInteractGui(pokemonID: UUID, canMountShoulder: Boolean, canGive
|
||||
val mountShoulder = InteractWheelOption(
|
||||
iconResource = cobblemonResource("textures/gui/interact/interact_wheel_icon_shoulder.png"),
|
||||
tooltipText = "cobblemon.ui.interact.mount.shoulder",
|
||||
enabled = canMountShoulder,
|
||||
enabled = { canMountShoulder },
|
||||
onPress = {
|
||||
if (canMountShoulder) {
|
||||
InteractPokemonPacket(pokemonID, InteractTypePokemon.SHOULDER).sendToServer()
|
||||
@@ -41,7 +45,7 @@ fun createPokemonInteractGui(pokemonID: UUID, canMountShoulder: Boolean, canGive
|
||||
val giveHeldItem = InteractWheelOption(
|
||||
iconResource = cobblemonResource("textures/gui/interact/interact_wheel_icon_held_item.png"),
|
||||
tooltipText = "cobblemon.ui.interact.give.item",
|
||||
enabled = canGiveHeld,
|
||||
enabled = { canGiveHeld },
|
||||
onPress = {
|
||||
if (canGiveHeld) {
|
||||
InteractPokemonPacket(pokemonID, InteractTypePokemon.HELD_ITEM).sendToServer()
|
||||
@@ -52,7 +56,7 @@ fun createPokemonInteractGui(pokemonID: UUID, canMountShoulder: Boolean, canGive
|
||||
val giveCosmeticItem = InteractWheelOption(
|
||||
iconResource = cobblemonResource("textures/gui/interact/interact_wheel_icon_cosmetic_item.png"),
|
||||
tooltipText = "cobblemon.ui.interact.give.cosmetic_item",
|
||||
enabled = canGiveCosmetic,
|
||||
enabled = { canGiveCosmetic },
|
||||
onPress = {
|
||||
if (canGiveCosmetic) {
|
||||
InteractPokemonPacket(pokemonID, InteractTypePokemon.COSMETIC_ITEM).sendToServer()
|
||||
@@ -64,7 +68,7 @@ fun createPokemonInteractGui(pokemonID: UUID, canMountShoulder: Boolean, canGive
|
||||
val ride = InteractWheelOption(
|
||||
iconResource = cobblemonResource("textures/gui/interact/interact_wheel_icon_ride.png"),
|
||||
tooltipText = "cobblemon.ui.interact.ride",
|
||||
enabled = canRide,
|
||||
enabled = { canRide },
|
||||
onPress = {
|
||||
if (canRide) {
|
||||
InteractPokemonPacket(pokemonID, InteractTypePokemon.RIDE).sendToServer()
|
||||
@@ -177,6 +181,35 @@ fun createPlayerInteractGui(optionsPacket: PlayerInteractOptionsPacket): Interac
|
||||
return InteractWheelGUI(options, Component.translatable("cobblemon.ui.interact.player"))
|
||||
}
|
||||
|
||||
fun createPokeSkillGui(player: AbstractClientPlayer, pokemon: Pokemon): InteractWheelGUI {
|
||||
val accessibleSkills = CobblemonPokeSkills.getAccessibleSkills(player, pokemon)
|
||||
val options: Multimap<Orientation, InteractWheelOption> = ArrayListMultimap.create()
|
||||
for (skill in accessibleSkills) {
|
||||
val skillOption = InteractWheelOption(
|
||||
iconResource = skill.icon,
|
||||
enabled = { skill.id !in pokemon.skillCooldownsTicks },
|
||||
tooltipText = skill.name,
|
||||
onPress = {
|
||||
CobblemonNetwork.sendToServer(UsePokeSkillPacket(skillId = skill.id, pokemonId = pokemon.uuid))
|
||||
closeGUI()
|
||||
}
|
||||
)
|
||||
when (options.size()) {
|
||||
0 -> options.put(Orientation.NORTH, skillOption)
|
||||
1 -> options.put(Orientation.NORTHEAST, skillOption)
|
||||
2 -> options.put(Orientation.SOUTHEAST, skillOption)
|
||||
3 -> options.put(Orientation.SOUTH, skillOption)
|
||||
4 -> options.put(Orientation.SOUTHWEST, skillOption)
|
||||
5 -> options.put(Orientation.NORTHWEST, skillOption)
|
||||
6 -> options.put(Orientation.WEST, skillOption)
|
||||
7 -> options.put(Orientation.EAST, skillOption)
|
||||
else -> break // We only have 8 slots
|
||||
}
|
||||
}
|
||||
|
||||
return PokeSkillWheelGUI(options, Component.translatable("cobblemon.ui.interact.poke_skill"))
|
||||
}
|
||||
|
||||
private fun getLangKey(status: PlayerInteractOptionsPacket.OptionStatus) : String {
|
||||
return when (status) {
|
||||
PlayerInteractOptionsPacket.OptionStatus.TOO_FAR -> "cobblemon.ui.interact.too_far"
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ import org.joml.Vector3f
|
||||
data class InteractWheelOption(
|
||||
val iconResource: ResourceLocation,
|
||||
val secondaryIconResource: ResourceLocation? = null,
|
||||
val enabled: Boolean = true,
|
||||
val enabled: () -> Boolean = { true },
|
||||
val tooltipText: String?,
|
||||
val colour: () -> Vector3f? = { null },
|
||||
val onPress: () -> Unit
|
||||
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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.interact.wheel
|
||||
|
||||
import com.google.common.collect.Multimap
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.network.chat.Component
|
||||
|
||||
class PokeSkillWheelGUI(
|
||||
private val options: Multimap<Orientation, InteractWheelOption>,
|
||||
title: Component
|
||||
) : InteractWheelGUI(options, title) {
|
||||
|
||||
/**
|
||||
* Due to the button being held swallow the event
|
||||
*/
|
||||
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
||||
if (button == 0) return false
|
||||
return super.mouseClicked(mouseX, mouseY, button)
|
||||
}
|
||||
|
||||
/**
|
||||
* On release will close the wheel and trigger the button press of the hovered button
|
||||
* TODO: make this wheel choose more like pizza slices.
|
||||
*/
|
||||
override fun mouseReleased(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
||||
if (button == 0) {
|
||||
// Manually trigger the hovered button's press
|
||||
buttons.forEach { btn ->
|
||||
if (btn.isMouseOver(mouseX, mouseY)) {
|
||||
btn.onClick(mouseX, mouseY)
|
||||
return true
|
||||
}
|
||||
}
|
||||
Minecraft.getInstance().setScreen(null)
|
||||
return true
|
||||
}
|
||||
return super.mouseReleased(mouseX, mouseY, button)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -32,8 +32,6 @@ import com.cobblemon.mod.common.client.ClientMoLangFunctions.setupClient
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.handleProfileDebugKeys
|
||||
import com.cobblemon.mod.common.client.gui.logProfileTranslations
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.BASE_HEIGHT
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.BASE_WIDTH
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.HALF_OVERLAY_WIDTH
|
||||
@@ -429,11 +427,6 @@ class PokedexGUI private constructor(
|
||||
override fun onClose() {
|
||||
if (blockPos != null) AdjustBlockEntityViewerCountPacket(blockPos, false).sendToServer()
|
||||
playSound(CobblemonSounds.POKEDEX_CLOSE)
|
||||
|
||||
selectedEntry?.speciesId?.let { speciesId ->
|
||||
logProfileTranslations(speciesId, pokemonInfoWidget.state)
|
||||
}
|
||||
|
||||
super.onClose()
|
||||
}
|
||||
|
||||
@@ -764,12 +757,6 @@ class PokedexGUI private constructor(
|
||||
return true
|
||||
}
|
||||
|
||||
if (!searchWidget.isFocused) {
|
||||
selectedEntry?.speciesId?.let { speciesId ->
|
||||
handleProfileDebugKeys(keyCode, speciesId, pokemonInfoWidget.state)
|
||||
}
|
||||
}
|
||||
|
||||
return super.keyPressed(keyCode, scanCode, modifiers)
|
||||
}
|
||||
|
||||
|
||||
+1
-3
@@ -22,7 +22,6 @@ import com.cobblemon.mod.common.api.types.ElementalType
|
||||
import com.cobblemon.mod.common.client.ClientMoLangFunctions.setupClient
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.ProfileTransformType
|
||||
import com.cobblemon.mod.common.client.gui.TypeIcon
|
||||
import com.cobblemon.mod.common.client.gui.drawProfilePokemon
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.HALF_OVERLAY_HEIGHT
|
||||
@@ -387,8 +386,7 @@ class PokemonInfoWidget(val pX: Int, val pY: Int, val updateForm: (PokedexForm)
|
||||
partialTicks = delta,
|
||||
rotation = Quaternionf().fromEulerXYZDegrees(rotationVector),
|
||||
state = state,
|
||||
blockLight = 15,
|
||||
profileTransformType = ProfileTransformType.POKEDEX,
|
||||
blockLight = 15
|
||||
)
|
||||
|
||||
matrices.popPose()
|
||||
|
||||
+1
-2
@@ -11,7 +11,6 @@ package com.cobblemon.mod.common.client.gui.pokedex.widgets
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.ProfileTransformType
|
||||
import com.cobblemon.mod.common.client.gui.drawProfilePokemon
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.HALF_OVERLAY_WIDTH
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.POKEMON_DESCRIPTION_HEIGHT
|
||||
@@ -91,7 +90,7 @@ class SizeWidget(val pX: Int, val pY: Int) : SoundlessWidget(
|
||||
rotation = Quaternionf().fromEulerXYZDegrees(Vector3f(0F, 0F, 0F)),
|
||||
state = FloatingState(),
|
||||
scale = modelScale,
|
||||
profileTransformType = ProfileTransformType.NONE,
|
||||
applyProfileTransform = false,
|
||||
applyBaseScale = true,
|
||||
r = 0F,
|
||||
g = 0F,
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.summary
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonItems
|
||||
import com.cobblemon.mod.common.CobblemonNetwork.sendToServer
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
@@ -20,8 +21,14 @@ import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.*
|
||||
import com.cobblemon.mod.common.client.gui.summary.widgets.*
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.ExitButton
|
||||
import com.cobblemon.mod.common.client.gui.TypeIcon
|
||||
import com.cobblemon.mod.common.client.gui.summary.widgets.EvolutionSelectScreen
|
||||
import com.cobblemon.mod.common.client.gui.summary.widgets.MarkingsWidget
|
||||
import com.cobblemon.mod.common.client.gui.summary.widgets.ModelWidget
|
||||
import com.cobblemon.mod.common.client.gui.summary.widgets.NicknameEntryWidget
|
||||
import com.cobblemon.mod.common.client.gui.summary.widgets.PartyWidget
|
||||
import com.cobblemon.mod.common.client.gui.summary.widgets.screens.SummaryTab
|
||||
import com.cobblemon.mod.common.client.gui.summary.widgets.screens.info.InfoWidget
|
||||
import com.cobblemon.mod.common.client.gui.summary.widgets.screens.marks.MarksWidget
|
||||
@@ -30,6 +37,7 @@ import com.cobblemon.mod.common.client.gui.summary.widgets.screens.moves.MovesWi
|
||||
import com.cobblemon.mod.common.client.gui.summary.widgets.screens.stats.StatWidget
|
||||
import com.cobblemon.mod.common.client.keybind.keybinds.SummaryBinding
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetItemHiddenPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.party.MovePartyPokemonPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.storage.party.SwapPartyPokemonPacket
|
||||
@@ -707,9 +715,27 @@ class Summary private constructor(party: Collection<Pokemon?>, private val edita
|
||||
) {
|
||||
this.focused = null
|
||||
}
|
||||
|
||||
handleProfileDebugKeys(keyCode, selectedPokemon.species.resourceIdentifier, modelWidget.state)
|
||||
|
||||
if (Cobblemon.config.enableDebugKeys) {
|
||||
val model = VaryingModelRepository.getPoser(selectedPokemon.species.resourceIdentifier, modelWidget.state)
|
||||
if (keyCode == InputConstants.KEY_UP) {
|
||||
model.profileTranslation = model.profileTranslation.add(0.0, -0.01, 0.0)
|
||||
}
|
||||
if (keyCode == InputConstants.KEY_DOWN) {
|
||||
model.profileTranslation = model.profileTranslation.add(0.0, 0.01, 0.0)
|
||||
}
|
||||
if (keyCode == InputConstants.KEY_LEFT) {
|
||||
model.profileTranslation = model.profileTranslation.add(-0.01, 0.0, 0.0)
|
||||
}
|
||||
if (keyCode == InputConstants.KEY_RIGHT) {
|
||||
model.profileTranslation = model.profileTranslation.add(0.01, 0.0, 0.0)
|
||||
}
|
||||
if (keyCode == InputConstants.KEY_EQUALS) {
|
||||
model.profileScale += 0.01F
|
||||
}
|
||||
if (keyCode == InputConstants.KEY_MINUS) {
|
||||
model.profileScale -= 0.01F
|
||||
}
|
||||
}
|
||||
return super.keyPressed(keyCode, scanCode, modifiers)
|
||||
}
|
||||
|
||||
@@ -718,8 +744,13 @@ class Summary private constructor(party: Collection<Pokemon?>, private val edita
|
||||
}
|
||||
|
||||
override fun onClose() {
|
||||
logProfileTranslations(selectedPokemon.species.resourceIdentifier, modelWidget.state)
|
||||
|
||||
if (Cobblemon.config.enableDebugKeys) {
|
||||
val model = VaryingModelRepository.getPoser(selectedPokemon.species.resourceIdentifier, modelWidget.state)
|
||||
Minecraft.getInstance().player?.sendSystemMessage(Component.literal("Profile Translation: ${model.profileTranslation}"))
|
||||
Minecraft.getInstance().player?.sendSystemMessage(Component.literal("Profile Scale: ${model.profileScale}"))
|
||||
Cobblemon.LOGGER.info("override var profileTranslation = Vec3d(${model.profileTranslation.x}, ${model.profileTranslation.y}, ${model.profileTranslation.z})")
|
||||
Cobblemon.LOGGER.info("override var profileScale = ${model.profileScale}F")
|
||||
}
|
||||
super.onClose()
|
||||
}
|
||||
}
|
||||
+1
-3
@@ -11,7 +11,6 @@ package com.cobblemon.mod.common.client.gui.summary.widgets
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.tags.CobblemonItemTags
|
||||
import com.cobblemon.mod.common.client.gui.ProfileTransformType
|
||||
import com.cobblemon.mod.common.client.gui.drawProfilePokemon
|
||||
import com.cobblemon.mod.common.client.gui.calculateHeadYawAndPitch
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.FloatingState
|
||||
@@ -117,8 +116,7 @@ class ModelWidget(
|
||||
partialTicks = partialTicks,
|
||||
headYaw = currentYawAndPitch.first,
|
||||
headPitch = currentYawAndPitch.second,
|
||||
blockLight = blockLight,
|
||||
profileTransformType = ProfileTransformType.SUMMARY,
|
||||
blockLight = blockLight
|
||||
)
|
||||
|
||||
heldItemRenderer.renderOnModel(
|
||||
|
||||
+71
-50
@@ -120,7 +120,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
fun getLogoResource(langCode: String?): ResourceLocation =
|
||||
logoResourceMap.entries.find { it.value.contains(langCode?.substringBefore("_")) }?.key ?: logo
|
||||
}
|
||||
|
||||
var selectedTM: TechnicalMachine? = null
|
||||
var heldStackMove: MoveTemplate? = null
|
||||
var tmList: SettableObservable<MutableList<TechnicalMachine>> = SettableObservable(mutableListOf())
|
||||
var output: ItemStack? = null
|
||||
@@ -159,8 +159,6 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
var oldIngredientItems: Array<Item> = arrayOf(Items.AIR, Items.AIR, Items.AIR)
|
||||
var oldResultTmSlotItem: Item = Items.AIR
|
||||
|
||||
var moveInfoTM: TechnicalMachine? = null
|
||||
|
||||
override fun init() {
|
||||
imageWidth = WIDTH
|
||||
imageHeight = HEIGHT
|
||||
@@ -173,8 +171,6 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
logoPosY = topPos + 1
|
||||
scanPosY = topPos + 1
|
||||
|
||||
menu.onSelectedTMUpdate = { updateSelectedTM(it) }
|
||||
|
||||
partySlotList.clear()
|
||||
CobblemonClient.storage.party.forEachIndexed { index, pokemon ->
|
||||
partySlotList.add(TMPartySlotWidget(
|
||||
@@ -230,14 +226,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
pX = leftPos + 4,
|
||||
pY = topPos + 29,
|
||||
tmList,
|
||||
setTM = { tm, clicked ->
|
||||
if (clicked) {
|
||||
if (tm != menu.currentlySelectedTM) SetActiveTMPacket(tm).sendToServer()
|
||||
setScreenFromMode(TM_BURN_MODE)
|
||||
} else {
|
||||
updateMoveInformation(tm)
|
||||
}
|
||||
}
|
||||
setTM = { tm, clicked -> setSelectedTM(tm, clicked) }
|
||||
)
|
||||
if (!children().contains(movesScrollingList)) addRenderableWidget(movesScrollingList)
|
||||
|
||||
@@ -263,21 +252,24 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
selectedMoveButton = MoveSlotButton(
|
||||
leftPos + 6,
|
||||
topPos + 6,
|
||||
move = menu.currentlySelectedTM?.moveName,
|
||||
pp = menu.currentlySelectedTM?.moveName?.pp ?: 0,
|
||||
move = selectedTM?.moveName,
|
||||
pp = selectedTM?.moveName?.pp ?: 0,
|
||||
ppAsFraction = false
|
||||
) {
|
||||
if ((it as MoveSlotButton).enabled) {
|
||||
if (::movesScrollingList.isInitialized && movesScrollingList.children().isEmpty()) setMoveList()
|
||||
playSound(CobblemonSounds.GUI_CLICK)
|
||||
setScreenFromMode(MOVE_SELECT_MODE)
|
||||
|
||||
// Clear active TM
|
||||
CobblemonNetwork.sendToServer(SetActiveTMPacket(null))
|
||||
}
|
||||
}
|
||||
if (!children().contains(selectedMoveButton)) addRenderableWidget(selectedMoveButton)
|
||||
|
||||
startButton = StartButton(leftPos + 5F, topPos + 35F) {
|
||||
if (!(it as StartButton).disabled) {
|
||||
menu.currentlySelectedTM?.let {
|
||||
selectedTM?.let {
|
||||
val burnActive = menu.containerData?.get(TMMachineBlockEntity.BURN_ACTIVE_INDEX) ?: 0
|
||||
CobblemonNetwork.sendToServer(SetTMMachineContainerDataPacket(
|
||||
TMMachineBlockEntity.BURN_ACTIVE_INDEX,
|
||||
@@ -292,14 +284,17 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
))
|
||||
}*/
|
||||
|
||||
//CobblemonNetwork.sendToServer(SetActiveTMPacket(it))
|
||||
CobblemonNetwork.sendToServer(SetActiveTMPacket(it))
|
||||
if (burnActive != 1) playSound(CobblemonSounds.TM_MACHINE_START)
|
||||
inventory.setChanged()
|
||||
menu.broadcastChanges()
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!children().contains(startButton)) addRenderableWidget(startButton)
|
||||
|
||||
setScreenFromMode(mode)
|
||||
initScreen = false
|
||||
|
||||
updateSlotItemMemory()
|
||||
}
|
||||
@@ -311,7 +306,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
if (scanPosY + 1 >= (topPos + SCREEN_SAVER_HEIGHT) * 2) scanPosY = 0
|
||||
|
||||
if (mode == TM_BURN_MODE) {
|
||||
menu.currentlySelectedTM?.let { tm ->
|
||||
selectedTM?.let { tm ->
|
||||
val resultStack = menu.inventory!!.getItem(TMMachineMenu.RESULT_SLOT)
|
||||
val craftedTmStack = ItemStack(CobblemonItems.TECHNICAL_MACHINE)
|
||||
.also { TMMoveComponent.setTMMove(it, tm.moveName) }
|
||||
@@ -344,7 +339,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
}
|
||||
|
||||
if (::selectedMoveButton.isInitialized) {
|
||||
selectedMoveButton.enabled = (heldStackMove == null || heldStackMove == menu.currentlySelectedTM?.moveName)
|
||||
selectedMoveButton.enabled = !isBurnActive() && (heldStackMove == null || heldStackMove == selectedTM?.moveName)
|
||||
}
|
||||
|
||||
if (isBurnActive()) {
|
||||
@@ -355,6 +350,9 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Check if screen should be switched upon opening UI
|
||||
if (!initScreen) loadBurnScreenData()
|
||||
}
|
||||
|
||||
if (heldMoveItemChanged) {
|
||||
@@ -402,6 +400,32 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
return wasScreenSaverActive
|
||||
}
|
||||
|
||||
private fun loadBurnScreenData() {
|
||||
var tm: TechnicalMachine? = null
|
||||
|
||||
val blockPos = menu.containerData?.let {
|
||||
val x = it.get(TMMachineBlockEntity.POSITION_X_INDEX)
|
||||
val y = it.get(TMMachineBlockEntity.POSITION_Y_INDEX)
|
||||
val z = it.get(TMMachineBlockEntity.POSITION_Z_INDEX)
|
||||
BlockPos(x, y, z)
|
||||
}
|
||||
|
||||
inventory.player.level().getBlockEntity(blockPos)?.let { blockEntity ->
|
||||
if (blockEntity is TMMachineBlockEntity) {
|
||||
Moves.getByName(blockEntity.activeMove)?.let {
|
||||
tm = TechnicalMachines.moveToTM[it]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If burn currently in progress or if active TM set, set to burn screen
|
||||
if (isBurnActive() || tm != null) {
|
||||
setSelectedTM(tm, true)
|
||||
}
|
||||
|
||||
initScreen = true
|
||||
}
|
||||
|
||||
private fun isBurnActive(): Boolean = (menu.containerData?.get(TMMachineBlockEntity.BURN_ACTIVE_INDEX) ?: 0) == 1
|
||||
|
||||
private fun setScreenFromMode(screen: Int) {
|
||||
@@ -443,6 +467,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
|
||||
private fun toggleTypeSelect(isVisible: Boolean) {
|
||||
if (isVisible) {
|
||||
setSelectedTM(null, false)
|
||||
if (::moveSearchWidget.isInitialized) moveSearchWidget.value = ""
|
||||
if (selectedPokemon != null) selectedPokemon = null
|
||||
sortType = null
|
||||
@@ -480,6 +505,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
}
|
||||
|
||||
private fun toggleTMBurn(isVisible: Boolean) {
|
||||
if (!isVisible) setSelectedTM(null, false)
|
||||
if (::selectedMoveButton.isInitialized) selectedMoveButton.visible = isVisible
|
||||
if (::startButton.isInitialized) startButton.visible = isVisible
|
||||
}
|
||||
@@ -490,40 +516,35 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
return if (learnableMoves.contains(move)) TMPartySlotWidget.CAN_LEARN else TMPartySlotWidget.CANNOT_LEARN
|
||||
}
|
||||
|
||||
fun updateSelectedTM(tm: TechnicalMachine?) {
|
||||
if (!initScreen) {
|
||||
initScreen = true
|
||||
setScreenFromMode(TM_BURN_MODE)
|
||||
tm?.let {
|
||||
sortType = ElementalTypes.get(tm.type)
|
||||
setMoveList()
|
||||
}
|
||||
fun setSelectedTM(tm: TechnicalMachine?, clicked: Boolean) {
|
||||
if (selectedTM != tm) {
|
||||
selectedTM = tm
|
||||
updatePartySlotStatus(tm?.moveName)
|
||||
}
|
||||
|
||||
if (mode == TM_BURN_MODE) updateMoveInformation(tm)
|
||||
|
||||
tm?.let {
|
||||
if (::selectedMoveButton.isInitialized) {
|
||||
selectedMoveButton.apply {
|
||||
move = it.moveName
|
||||
pp = it.moveName.pp
|
||||
}
|
||||
}
|
||||
if (::movesScrollingList.isInitialized) {
|
||||
movesScrollingList.setSlotHighlighted(if (clicked) null else selectedTM?.id)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateMoveInformation(tm: TechnicalMachine?) {
|
||||
moveInfoTM = tm
|
||||
|
||||
if (::moveDescriptionWidget.isInitialized) {
|
||||
val selectedDescription = tm?.moveName?.description?.string
|
||||
val selectedDescription = selectedTM?.moveName?.description?.string
|
||||
moveDescriptionWidget.setText(
|
||||
if (selectedDescription != null) listOf(selectedDescription) else emptyList()
|
||||
)
|
||||
}
|
||||
|
||||
if (::movesScrollingList.isInitialized) {
|
||||
movesScrollingList.setSlotHighlighted(tm?.id)
|
||||
if (clicked) {
|
||||
CobblemonNetwork.sendToServer(SetActiveTMPacket(tm))
|
||||
|
||||
selectedTM?.let {
|
||||
if (::selectedMoveButton.isInitialized) {
|
||||
selectedMoveButton.apply {
|
||||
move = it.moveName
|
||||
pp = it.moveName.pp
|
||||
}
|
||||
setScreenFromMode(TM_BURN_MODE)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -536,7 +557,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
}
|
||||
|
||||
fun renderDiscTypeOverlay(poseStack: PoseStack, isDiscRotating: Boolean, alpha: Float = 1F) {
|
||||
menu.currentlySelectedTM?.let {
|
||||
selectedTM?.let {
|
||||
val primaryRgb = it.moveName.elementalType.primaryColor.toRGB()
|
||||
val secondaryRgb = it.moveName.elementalType.secondaryColor.toRGB()
|
||||
blitk(
|
||||
@@ -685,7 +706,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
}
|
||||
|
||||
fun renderMoveInfo(context: GuiGraphics, mouseX: Int, mouseY: Int) {
|
||||
val moveTemplate = moveInfoTM?.moveName
|
||||
val moveTemplate = selectedTM?.moveName
|
||||
|
||||
blitk(
|
||||
matrixStack = context.pose(),
|
||||
@@ -1036,7 +1057,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
movesScrollingList.setDisabled(true, TechnicalMachines.moveToTM[heldStackMove])
|
||||
if (mode == MOVE_SELECT_MODE) {
|
||||
val heldStackTm = TechnicalMachines.moveToTM[heldStackMove]
|
||||
updateMoveInformation(if (tmList.get().contains(heldStackTm)) heldStackTm else null)
|
||||
setSelectedTM(if (tmList.get().contains(heldStackTm)) heldStackTm else null, false)
|
||||
|
||||
// Scroll to move if moves list contains held TM move
|
||||
if (tmList.get().contains(heldStackTm)) {
|
||||
@@ -1056,8 +1077,8 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
heldStackMove = null
|
||||
|
||||
// Reset selected move on move select screen
|
||||
if (mode == MOVE_SELECT_MODE) updateMoveInformation(null)
|
||||
updatePartySlotStatus(menu.currentlySelectedTM?.moveName)
|
||||
if (mode == MOVE_SELECT_MODE) setSelectedTM(null, false)
|
||||
updatePartySlotStatus(selectedTM?.moveName)
|
||||
|
||||
if (::movesScrollingList.isInitialized) {
|
||||
movesScrollingList.setDisabled(false)
|
||||
@@ -1134,7 +1155,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
if (isInventoryKeyPressed(minecraft, keyCode, scanCode)) {
|
||||
if (searchFocused) { return true }
|
||||
else {
|
||||
onClose()
|
||||
Minecraft.getInstance().setScreen(null)
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -1145,7 +1166,7 @@ class TMMachineScreen(containerMenu: TMMachineMenu, val inventory: Inventory, ti
|
||||
this.focused = null
|
||||
return true
|
||||
} else {
|
||||
onClose()
|
||||
Minecraft.getInstance().setScreen(null)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
+11
-21
@@ -15,6 +15,7 @@ import com.cobblemon.mod.common.battles.BattleFormat
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.battle.ClientBattle
|
||||
import com.cobblemon.mod.common.client.gui.battle.BattleGUI
|
||||
import com.cobblemon.mod.common.client.gui.interact.wheel.createPokeSkillGui
|
||||
import com.cobblemon.mod.common.client.keybind.CobblemonBlockingKeyBinding
|
||||
import com.cobblemon.mod.common.client.keybind.KeybindCategories
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
@@ -26,12 +27,12 @@ import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.isUsingPokedex
|
||||
import com.cobblemon.mod.common.util.traceFirstEntityCollision
|
||||
import com.mojang.blaze3d.platform.InputConstants
|
||||
import kotlin.math.pow
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.player.LocalPlayer
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.level.ClipContext
|
||||
import kotlin.math.pow
|
||||
|
||||
object PartySendBinding : CobblemonBlockingKeyBinding(
|
||||
"key.cobblemon.throwpartypokemon",
|
||||
@@ -39,32 +40,17 @@ object PartySendBinding : CobblemonBlockingKeyBinding(
|
||||
InputConstants.KEY_R,
|
||||
KeybindCategories.COBBLEMON_CATEGORY
|
||||
) {
|
||||
const val POKE_SKILL_TIME = 0.7F
|
||||
var canApplyChange = true
|
||||
var heldDownSeconds = 0F
|
||||
|
||||
fun actioned() {
|
||||
canApplyChange = false
|
||||
wasDown = true
|
||||
heldDownSeconds = 0F
|
||||
}
|
||||
|
||||
fun canAction() = canApplyChange && Minecraft.getInstance().player?.isUsingPokedex() == false
|
||||
|
||||
override fun onTick() {
|
||||
if (wasDown) {
|
||||
if (heldDownSeconds < 100) {
|
||||
heldDownSeconds += Minecraft.getInstance().timer.getGameTimeDeltaPartialTick(false)
|
||||
}
|
||||
} else {
|
||||
heldDownSeconds = 0F
|
||||
}
|
||||
|
||||
super.onTick()
|
||||
}
|
||||
|
||||
override fun onRelease() {
|
||||
val canAction = canAction()
|
||||
wasDown = false
|
||||
canApplyChange = true
|
||||
if (!canAction) {
|
||||
return
|
||||
@@ -105,7 +91,8 @@ object PartySendBinding : CobblemonBlockingKeyBinding(
|
||||
entityClass = LivingEntity::class.java,
|
||||
ignoreEntity = player,
|
||||
maxDistance = Cobblemon.config.battleSpectateMaxDistance,
|
||||
collideBlock = ClipContext.Fluid.NONE)
|
||||
collideBlock = ClipContext.Fluid.NONE
|
||||
)
|
||||
if (canSendOutPokemon(player, targetEntity)) {
|
||||
sendToServer(SendOutPokemonPacket(CobblemonClient.storage.selectedSlot))
|
||||
} else {
|
||||
@@ -127,10 +114,13 @@ object PartySendBinding : CobblemonBlockingKeyBinding(
|
||||
//The server sends a packet back that opens the player interaction menu with the proper options
|
||||
sendToServer(RequestPlayerInteractionsPacket(entity.uuid, entity.id, pokemon.uuid))
|
||||
}
|
||||
|
||||
is PokemonEntity -> {
|
||||
if (!entity.canBattle(player) || entity.position().distanceToSqr(player.position()) > Cobblemon.config.battleWildMaxDistance.pow(2)) return
|
||||
sendToServer(BattleChallengePacket(entity.id, pokemon.uuid, BattleFormat.GEN_9_SINGLES))
|
||||
}
|
||||
if (!entity.canBattle(player) || entity.position()
|
||||
.distanceToSqr(player.position()) > Cobblemon.config.battleWildMaxDistance.pow(2)
|
||||
) return
|
||||
sendToServer(BattleChallengePacket(entity.id, pokemon.uuid, BattleFormat.GEN_9_SINGLES))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+13
-1
@@ -19,6 +19,7 @@ import com.cobblemon.mod.common.entity.PosableEntity
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.SpawnSnowstormEntityParticlePacket
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
object SpawnSnowstormEntityParticleHandler : ClientNetworkPacketHandler<SpawnSnowstormEntityParticlePacket> {
|
||||
override fun handle(packet: SpawnSnowstormEntityParticlePacket, client: Minecraft) {
|
||||
@@ -31,6 +32,7 @@ object SpawnSnowstormEntityParticleHandler : ClientNetworkPacketHandler<SpawnSno
|
||||
val targetState = (targetedEntity as? PosableEntity)?.delegate as? PosableState
|
||||
val sourceLocators = packet.sourceLocators.firstNotNullOfOrNull { sourceState.getMatchingLocators(it).takeIf { it.isNotEmpty() } } ?: return
|
||||
val targetedLocator = packet.targetLocators?.firstOrNull { targetState?.getMatchingLocators(it)?.isNotEmpty() == true }
|
||||
val targetPosition = packet.targetPosition
|
||||
val rootMatrix = sourceState.locatorStates["root"]!!
|
||||
|
||||
sourceLocators.forEach { locator ->
|
||||
@@ -40,6 +42,16 @@ object SpawnSnowstormEntityParticleHandler : ClientNetworkPacketHandler<SpawnSno
|
||||
val particleRuntime = MoLangRuntime().setup().setupClient()
|
||||
particleRuntime.environment.query.addFunction("entity") { sourceState.runtime.environment.query }
|
||||
|
||||
// Target resolution priority: entity+locator > world position > none
|
||||
val targetPos: (() -> Vec3)? = if (targetedEntity != null) {
|
||||
{ targetedLocator?.let { targetState?.locatorStates?.get(it) }?.getOrigin() ?: targetedEntity.position() }
|
||||
} else if (targetPosition != null) {
|
||||
val pos = packet.targetPosition
|
||||
{ pos }
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
val storm = ParticleStorm(
|
||||
effect = effect,
|
||||
emitterSpaceMatrix = particleMatrix,
|
||||
@@ -49,7 +61,7 @@ object SpawnSnowstormEntityParticleHandler : ClientNetworkPacketHandler<SpawnSno
|
||||
sourceVelocity = { sourceEntity.deltaMovement },
|
||||
sourceAlive = { !sourceEntity.isRemoved },
|
||||
sourceVisible = { !sourceEntity.isInvisible },
|
||||
targetPos = if (targetedEntity != null) { { targetedLocator?.let { targetState?.locatorStates?.get(it) }?.getOrigin() ?: targetedEntity.position() } } else null,
|
||||
targetPos = targetPos,
|
||||
entity = sourceEntity
|
||||
)
|
||||
|
||||
|
||||
+4
-11
@@ -19,6 +19,7 @@ import net.minecraft.world.level.block.Block
|
||||
object SetActiveTMPacketHandler : ServerNetworkPacketHandler<SetActiveTMPacket> {
|
||||
override fun handle(packet: SetActiveTMPacket, server: MinecraftServer, player: ServerPlayer) {
|
||||
val menu = player.containerMenu as? TMMachineMenu ?: return
|
||||
val inventory = menu.inventory ?: return
|
||||
val tmData = Cobblemon.playerDataManager.getTMData(player)
|
||||
|
||||
if (packet.tm != null && (!packet.tm.isPassivelyObtained() && packet.tm.id !in tmData.learnedTMs)) {
|
||||
@@ -29,17 +30,9 @@ object SetActiveTMPacketHandler : ServerNetworkPacketHandler<SetActiveTMPacket>
|
||||
blockEntity.activeMove = packet.tm?.moveName?.name ?: ""
|
||||
blockEntity.setChanged()
|
||||
player.level().sendBlockUpdated(blockEntity.blockPos, blockEntity.blockState, blockEntity.blockState, Block.UPDATE_CLIENTS)
|
||||
|
||||
blockEntity.burnActive = false
|
||||
blockEntity.burnProgress = 0
|
||||
|
||||
player.level().players().forEach { thePlayer -> //Update all players with matching menu/blockentity
|
||||
val tmmMenu = thePlayer.containerMenu as? TMMachineMenu ?: return@forEach
|
||||
if (tmmMenu.tmMachineEntity == blockEntity) {
|
||||
tmmMenu.currentlySelectedTM = packet.tm
|
||||
tmmMenu.broadcastChanges()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inventory.setChanged()
|
||||
menu.broadcastChanges()
|
||||
}
|
||||
}
|
||||
-21
@@ -1,21 +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.net.gui
|
||||
|
||||
import com.cobblemon.mod.common.api.net.ClientNetworkPacketHandler
|
||||
import com.cobblemon.mod.common.block.tmmachine.TMMachineMenu
|
||||
import com.cobblemon.mod.common.net.messages.client.ui.SynchronizeActiveTMPacket
|
||||
import net.minecraft.client.Minecraft
|
||||
|
||||
object SynchronizeActiveTMHandler: ClientNetworkPacketHandler<SynchronizeActiveTMPacket> {
|
||||
override fun handle(packet: SynchronizeActiveTMPacket, client: Minecraft) {
|
||||
val tmmMenu = client.player?.containerMenu as? TMMachineMenu ?: return
|
||||
tmmMenu.clientSetSelectedTM(packet.tm)
|
||||
}
|
||||
}
|
||||
-5
@@ -134,11 +134,6 @@ open class PosableModel(@Transient override val rootPart: Bone) : ModelFrame {
|
||||
*/
|
||||
open var profileTranslation = Vec3(0.0, 0.0, 0.0)
|
||||
|
||||
open var profilePokedexScale: Float? = null
|
||||
open var profilePokedexTranslation: Vec3? = null
|
||||
open var profileSummaryScale: Float? = null
|
||||
open var profileSummaryTranslation: Vec3? = null
|
||||
|
||||
var red = 1F
|
||||
var green = 1F
|
||||
var blue = 1F
|
||||
|
||||
@@ -10,6 +10,13 @@ package com.cobblemon.mod.common.data
|
||||
|
||||
import com.cobblemon.mod.common.*
|
||||
import com.cobblemon.mod.common.Cobblemon.LOGGER
|
||||
import com.cobblemon.mod.common.CobblemonBehaviours
|
||||
import com.cobblemon.mod.common.CobblemonCallbacks
|
||||
import com.cobblemon.mod.common.CobblemonCosmeticItems
|
||||
import com.cobblemon.mod.common.CobblemonMechanics
|
||||
import com.cobblemon.mod.common.CobblemonPokeSkills
|
||||
import com.cobblemon.mod.common.CobblemonRideSettings
|
||||
import com.cobblemon.mod.common.CobblemonUnlockableWallpapers
|
||||
import com.cobblemon.mod.common.api.abilities.Abilities
|
||||
import com.cobblemon.mod.common.api.berry.Berries
|
||||
import com.cobblemon.mod.common.api.cooking.Seasonings
|
||||
@@ -73,6 +80,7 @@ object CobblemonDataProvider : DataProvider {
|
||||
this.register(GlobalSpeciesFeatures, reloadable = false)
|
||||
this.register(SpeciesFeatureAssignments, reloadable = false)
|
||||
this.register(ActionEffects, reloadable = true)
|
||||
this.register(CobblemonPokeSkills, reloadable = true)
|
||||
this.register(Moves, reloadable = false)
|
||||
this.register(CobblemonMovesetBuilders, reloadable = false)
|
||||
this.register(Abilities, reloadable = false)
|
||||
|
||||
@@ -0,0 +1,360 @@
|
||||
/*
|
||||
* 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.entity.pokemon
|
||||
|
||||
import com.bedrockk.molang.runtime.MoLangRuntime
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
|
||||
import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectTimeline
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffects
|
||||
import com.cobblemon.mod.common.api.moves.animations.TargetsProvider
|
||||
import com.cobblemon.mod.common.api.moves.animations.UsersProvider
|
||||
import com.cobblemon.mod.common.api.pokemon.status.Statuses
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.blockRegistry
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.codec.EXPRESSION_LIKE_CODEC
|
||||
import com.cobblemon.mod.common.util.isInBattle
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import net.minecraft.core.registries.Registries
|
||||
import net.minecraft.network.codec.ByteBufCodecs
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.BlockHitResult
|
||||
import net.minecraft.world.phys.HitResult
|
||||
|
||||
/**
|
||||
* The reference object for a skill that a Pokémon can use in the overworld.
|
||||
*
|
||||
* Most skills are "wrapper" skills that play a move's action effect at a target and run
|
||||
* some MoLang on impact. Custom skills can define a full action effect timeline.
|
||||
*
|
||||
* Access is auto-derived from grantingMoves/Abilities/Types/Species lists. If none are
|
||||
* populated, accessCondition is used as a fallback.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since August 31st, 2025
|
||||
*/
|
||||
class PokeSkill(
|
||||
val name: String,
|
||||
val enabled: Boolean = true,
|
||||
val actionEffect: ActionEffectTimeline,
|
||||
val icon: ResourceLocation,
|
||||
val cooldownTicks: Int,
|
||||
val accessCondition: ExpressionLike = "true".asExpressionLike(),
|
||||
val useCondition: ExpressionLike = "true".asExpressionLike(),
|
||||
// Targeting
|
||||
val targetType: TargetType? = null,
|
||||
val range: Double? = null,
|
||||
val targetCondition: ExpressionLike? = null,
|
||||
// Granting
|
||||
val grantingMoves: List<String>? = null,
|
||||
val grantingAbilities: List<String>? = null,
|
||||
val grantingTypes: List<String>? = null,
|
||||
val grantingSpecies: List<String>? = null,
|
||||
// Wrapper skill fields
|
||||
val hitDelay: ExpressionLike? = null,
|
||||
val hitEffect: ResourceLocation? = null,
|
||||
val fallbackActionEffect: ResourceLocation? = null
|
||||
) {
|
||||
// Enum to determine what this skill will target.
|
||||
enum class TargetType {
|
||||
NONE, SELF, BLOCK, ENTITY, BOTH
|
||||
}
|
||||
|
||||
companion object {
|
||||
val runtime = MoLangRuntime().setup()
|
||||
val CODEC = RecordCodecBuilder.create<PokeSkill> { instance ->
|
||||
instance.group(
|
||||
Codec.STRING.fieldOf("name").forGetter { it.name },
|
||||
Codec.BOOL.fieldOf("enabled").forGetter { it.enabled },
|
||||
Codec.unit<ActionEffectTimeline> { ActionEffectTimeline.NONE }.fieldOf("actionEffect").forGetter { it.actionEffect },
|
||||
ResourceLocation.CODEC.fieldOf("icon").forGetter { it.icon },
|
||||
Codec.INT.fieldOf("cooldownTicks").forGetter { it.cooldownTicks },
|
||||
EXPRESSION_LIKE_CODEC.fieldOf("accessCondition").forGetter { it.accessCondition },
|
||||
EXPRESSION_LIKE_CODEC.fieldOf("useCondition").forGetter { it.useCondition }
|
||||
).apply(instance, ::PokeSkill)
|
||||
}
|
||||
val PACKET_CODEC = ByteBufCodecs.fromCodecWithRegistries(CODEC)
|
||||
private val DEFAULT_ACTION_EFFECT = cobblemonResource("default_poke_skill")
|
||||
}
|
||||
|
||||
@Transient
|
||||
lateinit var id: ResourceLocation
|
||||
|
||||
|
||||
// fun canAccess(player: Player, pokemon: Pokemon): Boolean {
|
||||
// if (!enabled) {
|
||||
// return false
|
||||
// }
|
||||
//
|
||||
// runtime.withQueryValue("player", player.asMostSpecificMoLangValue())
|
||||
// runtime.withQueryValue("pokemon", pokemon.struct)
|
||||
// pokemon.entity?.let { runtime.withQueryValue("entity", it.asMostSpecificMoLangValue()) }
|
||||
// val hasAccess = runtime.resolveBoolean(accessCondition)
|
||||
// return hasAccess
|
||||
// }
|
||||
|
||||
/**
|
||||
* Determines access by checking the pokemons data against the granting lists.
|
||||
* If no granting lists are populated, accessCondition is used as a fallback.
|
||||
*/
|
||||
fun canAccess(player: Player, pokemon: Pokemon): Boolean {
|
||||
if (!enabled) {
|
||||
return false
|
||||
}
|
||||
|
||||
// Check granting lists — if any are populated, check if the player has any of the listed moves/abilities/types/species
|
||||
val hasGrantingLists = !grantingMoves.isNullOrEmpty() || !grantingAbilities.isNullOrEmpty() ||
|
||||
!grantingTypes.isNullOrEmpty() || !grantingSpecies.isNullOrEmpty()
|
||||
|
||||
if (hasGrantingLists) {
|
||||
val moveMatch = !grantingMoves.isNullOrEmpty() && grantingMoves.any { moveName ->
|
||||
pokemon.moveSet.any { it.template.name == moveName }
|
||||
}
|
||||
val abilityMatch = !grantingAbilities.isNullOrEmpty() && grantingAbilities.any { abilityName ->
|
||||
pokemon.ability.name == abilityName
|
||||
}
|
||||
val typeMatch = !grantingTypes.isNullOrEmpty() && grantingTypes.any { typeName ->
|
||||
pokemon.types.any { it.name.equals(typeName, ignoreCase = true) }
|
||||
}
|
||||
val speciesMatch = !grantingSpecies.isNullOrEmpty() && grantingSpecies.any { speciesName ->
|
||||
pokemon.species.name.equals(speciesName, ignoreCase = true)
|
||||
}
|
||||
|
||||
if (!(moveMatch || abilityMatch || typeMatch || speciesMatch)) return false
|
||||
}
|
||||
|
||||
// Always evaluate accessCondition — acts as additional gate when granting lists are present,
|
||||
// or as the sole gate when no granting lists are populated
|
||||
runtime.withQueryValue("player", player.asMostSpecificMoLangValue())
|
||||
runtime.withQueryValue("pokemon", pokemon.struct)
|
||||
pokemon.entity?.let { runtime.withQueryValue("entity", it.asMostSpecificMoLangValue()) }
|
||||
return runtime.resolveBoolean(accessCondition ?: "true".asExpressionLike())
|
||||
}
|
||||
|
||||
fun canUse(player: Player, pokemon: Pokemon): Boolean {
|
||||
val status = pokemon.status?.status
|
||||
if (id in pokemon.skillCooldownsTicks || player.isInBattle() || status == Statuses.SLEEP || status == Statuses.FROZEN) {
|
||||
return false
|
||||
}
|
||||
runtime.withQueryValue("player", player.asMostSpecificMoLangValue())
|
||||
runtime.withQueryValue("pokemon", pokemon.struct)
|
||||
val canUse = runtime.resolveBoolean(useCondition)
|
||||
return canUse
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves which move from the pokemon's moveset grants this skill.
|
||||
* Returns the first matching move name from grantingMoves, or null if none match.
|
||||
*/
|
||||
fun resolveGrantingMove(pokemon: Pokemon): String? {
|
||||
if (grantingMoves.isNullOrEmpty()) return null // need this guard
|
||||
return grantingMoves.firstOrNull { moveName ->
|
||||
pokemon.moveSet.any { it.template.name == moveName }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the action effect to use for the move visual.
|
||||
* Priority: granting move's action effect > fallbackActionEffect > null
|
||||
*/
|
||||
fun resolveVisualEffect(pokemon: Pokemon): ResourceLocation? {
|
||||
val grantingMove = resolveGrantingMove(pokemon)
|
||||
if (grantingMove != null) {
|
||||
val effectId = cobblemonResource(grantingMove)
|
||||
if (ActionEffects.actionEffects.containsKey(effectId)) return effectId
|
||||
Cobblemon.LOGGER.warn("PokeSkill '$id': granting move '$grantingMove' has no action effect at '$effectId'")
|
||||
}
|
||||
return fallbackActionEffect
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the skill on the given pokemon.
|
||||
* Populates context and runs targeting logic.
|
||||
*/
|
||||
fun use(
|
||||
player: ServerPlayer,
|
||||
pokemon: Pokemon,
|
||||
// context information!!!
|
||||
): Boolean {
|
||||
if (!canUse(player, pokemon)) return false
|
||||
val entity = pokemon.entity ?: return false
|
||||
val level = player.level() as? ServerLevel ?: return false
|
||||
// I think these should be defaulted but making them nullable means I don't have to adjust the
|
||||
// other jsons that don't populate them yet...
|
||||
val effectiveTargetType = targetType ?: TargetType.NONE
|
||||
val effectiveRange = range ?: 8.0
|
||||
|
||||
// Resolve the action effect to run
|
||||
val effectTimeline = if (actionEffect != null && actionEffect != ActionEffectTimeline.NONE) {
|
||||
actionEffect
|
||||
} else {
|
||||
ActionEffects.actionEffects[DEFAULT_ACTION_EFFECT] ?: run {
|
||||
Cobblemon.LOGGER.warn("PokeSkill '$id': default_poke_skill action effect not found")
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Set up runtime
|
||||
val skillRuntime = MoLangRuntime().setup()
|
||||
skillRuntime.withQueryValue("player", player.asMostSpecificMoLangValue())
|
||||
skillRuntime.withQueryValue("pokemon", pokemon.struct)
|
||||
skillRuntime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
skillRuntime.environment.setSimpleVariable("skill_id", StringValue(id.toString()))
|
||||
skillRuntime.environment.setSimpleVariable("target_type", StringValue(effectiveTargetType.name.lowercase()))
|
||||
skillRuntime.environment.query.addFunction("missed") { DoubleValue(0.0) } // move action effects use this to determine if the target particles should play. We want them to always play for skills I believe
|
||||
|
||||
|
||||
// Targeting — raycast based on targetType
|
||||
when (effectiveTargetType) {
|
||||
TargetType.SELF -> {
|
||||
injectEntityTarget(skillRuntime, player)
|
||||
skillRuntime.environment.setSimpleVariable("target_is_entity", DoubleValue(1.0))
|
||||
}
|
||||
TargetType.BLOCK -> {
|
||||
val blockHit = getPlayerLookedBlock(player, effectiveRange)
|
||||
if (blockHit == null) return false
|
||||
injectBlockTarget(skillRuntime, blockHit, level)
|
||||
skillRuntime.environment.setSimpleVariable("target_is_entity", DoubleValue(0.0))
|
||||
}
|
||||
TargetType.ENTITY -> {
|
||||
val entityHit = getPlayerLookedEntity(player, effectiveRange)
|
||||
if (entityHit == null) return false
|
||||
injectEntityTarget(skillRuntime, entityHit)
|
||||
skillRuntime.environment.setSimpleVariable("target_is_entity", DoubleValue(1.0))
|
||||
}
|
||||
TargetType.BOTH -> {
|
||||
val entityHit = getPlayerLookedEntity(player, effectiveRange)
|
||||
if (entityHit != null) {
|
||||
injectEntityTarget(skillRuntime, entityHit)
|
||||
skillRuntime.environment.setSimpleVariable("target_is_entity", DoubleValue(1.0))
|
||||
} else {
|
||||
val blockHit = getPlayerLookedBlock(player, effectiveRange)
|
||||
if (blockHit == null) return false
|
||||
injectBlockTarget(skillRuntime, blockHit, level)
|
||||
skillRuntime.environment.setSimpleVariable("target_is_entity", DoubleValue(0.0))
|
||||
}
|
||||
}
|
||||
TargetType.NONE -> {}
|
||||
}
|
||||
|
||||
// Evaluate target condition
|
||||
if (targetCondition != null && !skillRuntime.resolveBoolean(targetCondition)) return false
|
||||
|
||||
// Inject wrapper skill variables
|
||||
val visualEffect = resolveVisualEffect(pokemon)
|
||||
if (visualEffect != null) {
|
||||
skillRuntime.environment.setSimpleVariable("granting_move", StringValue(visualEffect.toString()))
|
||||
}
|
||||
if (hitEffect != null) {
|
||||
skillRuntime.environment.setSimpleVariable("hit_effect", StringValue(hitEffect.toString()))
|
||||
}
|
||||
if (hitDelay != null) {
|
||||
skillRuntime.environment.setSimpleVariable("hit_delay", hitDelay.resolve(skillRuntime))
|
||||
}
|
||||
|
||||
|
||||
// Build providers
|
||||
val providers = mutableListOf<Any>(
|
||||
UsersProvider(entity)
|
||||
)
|
||||
|
||||
// Build and run context
|
||||
val context = ActionEffectContext(
|
||||
actionEffect = effectTimeline,
|
||||
runtime = skillRuntime,
|
||||
providers = providers,
|
||||
level = level
|
||||
)
|
||||
|
||||
effectTimeline.run(context).thenRun {
|
||||
// Auto-apply cooldown after effect completes
|
||||
pokemon.skillCooldownsTicks[id] = cooldownTicks
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility functions for setting up the runtime for a skill.
|
||||
*/
|
||||
private fun injectBlockTarget(runtime: MoLangRuntime, blockHit: BlockHitResult, level: ServerLevel) {
|
||||
val pos = blockHit.blockPos
|
||||
runtime.environment.setSimpleVariable("target_x", DoubleValue(pos.x + 0.5))
|
||||
runtime.environment.setSimpleVariable("target_y", DoubleValue(pos.y + 0.5))
|
||||
runtime.environment.setSimpleVariable("target_z", DoubleValue(pos.z + 0.5))
|
||||
runtime.environment.setSimpleVariable("target_block_x", DoubleValue(pos.x.toDouble()))
|
||||
runtime.environment.setSimpleVariable("target_block_y", DoubleValue(pos.y.toDouble()))
|
||||
runtime.environment.setSimpleVariable("target_block_z", DoubleValue(pos.z.toDouble()))
|
||||
|
||||
val blockState = level.getBlockState(pos)
|
||||
val blockHolder = level.blockRegistry.wrapAsHolder(blockState.block)
|
||||
val blockValue = blockHolder.asMoLangValue(Registries.BLOCK)
|
||||
|
||||
blockValue.addFunction("x") { DoubleValue(pos.x.toDouble()) }
|
||||
blockValue.addFunction("y") { DoubleValue(pos.y.toDouble()) }
|
||||
blockValue.addFunction("z") { DoubleValue(pos.z.toDouble()) }
|
||||
|
||||
runtime.environment.setSimpleVariable("target_block", blockValue)
|
||||
}
|
||||
|
||||
private fun injectEntityTarget(runtime: MoLangRuntime, entityHit: Entity) {
|
||||
runtime.environment.setSimpleVariable("target_x", DoubleValue(entityHit.x))
|
||||
runtime.environment.setSimpleVariable("target_y", DoubleValue(entityHit.y + entityHit.bbHeight / 2.0))
|
||||
runtime.environment.setSimpleVariable("target_z", DoubleValue(entityHit.z))
|
||||
runtime.environment.setSimpleVariable("target_entity", entityHit.asMostSpecificMoLangValue())
|
||||
}
|
||||
|
||||
/**
|
||||
* simple raycast to get the block the player is looking at.
|
||||
*/
|
||||
private fun getPlayerLookedBlock(player: ServerPlayer, range: Double): BlockHitResult? {
|
||||
val hitResult = player.pick(range, 0f, true)
|
||||
return if (hitResult.type == HitResult.Type.BLOCK) hitResult as BlockHitResult else null
|
||||
}
|
||||
|
||||
/**
|
||||
* Raycast to determine the entity the player is looking at
|
||||
*/
|
||||
private fun getPlayerLookedEntity(player: ServerPlayer, range: Double): Entity? {
|
||||
val eyePosition = player.getEyePosition(1.0f)
|
||||
val lookVector = player.getViewVector(1.0f)
|
||||
val reachVector = eyePosition.add(lookVector.x * range, lookVector.y * range, lookVector.z * range)
|
||||
|
||||
// Create an outer bounding box to find potential candidates
|
||||
val searchBox = player.boundingBox.expandTowards(lookVector.scale(range)).inflate(1.0, 1.0, 1.0)
|
||||
|
||||
// Filter entities within the search box
|
||||
val entityHitResult = net.minecraft.world.entity.projectile.ProjectileUtil.getEntityHitResult(
|
||||
player,
|
||||
eyePosition,
|
||||
reachVector,
|
||||
searchBox,
|
||||
{ entity -> !entity.isSpectator && entity.isPickable },
|
||||
range * range
|
||||
)
|
||||
|
||||
return entityHitResult?.entity
|
||||
}
|
||||
}
|
||||
@@ -20,12 +20,13 @@ object ServerTickHandler {
|
||||
|
||||
secondsTick++
|
||||
|
||||
if (secondsTick == 20) {
|
||||
secondsTick = 0
|
||||
|
||||
// Party tick
|
||||
for (player in server.playerList.players) {
|
||||
player.party().onSecondPassed(player)
|
||||
// Party tick
|
||||
for (player in server.playerList.players) {
|
||||
val party = player.party()
|
||||
party.forEach { it.tickSkillCooldowns() }
|
||||
if (secondsTick == 20) {
|
||||
secondsTick = 0
|
||||
party.onSecondPassed(player)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ import net.minecraft.world.level.block.Block
|
||||
class StatusCureItem(val itemName: String, vararg val status: Status, block: Block) : ItemNameBlockItem(block, Properties()), PokemonSelectingItem {
|
||||
override val bagItem = object : BagItem {
|
||||
override val itemName = this@StatusCureItem.itemName
|
||||
override val returnItem = Items.GLASS_BOTTLE
|
||||
override val returnItem = Items.AIR
|
||||
override fun canUse(stack: ItemStack, battle: PokemonBattle, target: BattlePokemon) = canUseOnPokemon(stack, target.effectedPokemon)
|
||||
override fun getShowdownInput(actor: BattleActor, battlePokemon: BattlePokemon, data: String?) = "cure_status${status.takeIf { it.isNotEmpty() }?.let { " ${it.joinToString(separator = " ") { it.showdownName } }" } ?: "" }"
|
||||
}
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.CobblemonPokeSkills
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokeSkill
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
|
||||
class PokeSkillsRegistrySyncPacket(
|
||||
pokeSkills: Collection<PokeSkill>
|
||||
) : DataRegistrySyncPacket<PokeSkill, PokeSkillsRegistrySyncPacket>(pokeSkills) {
|
||||
|
||||
override val id = ID
|
||||
|
||||
override fun encodeEntry(buffer: RegistryFriendlyByteBuf, entry: PokeSkill) {
|
||||
PokeSkill.PACKET_CODEC.encode(buffer, entry)
|
||||
}
|
||||
|
||||
override fun decodeEntry(buffer: RegistryFriendlyByteBuf): PokeSkill? {
|
||||
return PokeSkill.PACKET_CODEC.decode(buffer)
|
||||
}
|
||||
|
||||
override fun synchronizeDecoded(entries: Collection<PokeSkill>) {
|
||||
CobblemonPokeSkills.reload(entries.associateBy { it.id })
|
||||
}
|
||||
|
||||
companion object {
|
||||
val ID = cobblemonResource("poke_skill_sync")
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) = PokeSkillsRegistrySyncPacket(emptyList()).apply { decodeBuffer(buffer) }
|
||||
}
|
||||
}
|
||||
+14
-2
@@ -13,10 +13,15 @@ import com.cobblemon.mod.common.client.net.effect.SpawnSnowstormEntityParticleHa
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
/**
|
||||
* Packet that spawns a snowstorm particle effect on a specified entity and specified locator.
|
||||
* Can specify an optional target+locator to pass through to the spawned particle
|
||||
* Can alternatively specify a [targetPosition] for entity-to-world-position targeting
|
||||
* (e.g. a Pokémon firing particles at a block).
|
||||
*
|
||||
* Target resolution priority: targetedEntityId + targetLocators > targetPosition > no target
|
||||
*
|
||||
* Handled by [SpawnSnowstormEntityParticleHandler]
|
||||
*
|
||||
@@ -28,7 +33,8 @@ class SpawnSnowstormEntityParticlePacket(
|
||||
val sourceEntityId: Int,
|
||||
val sourceLocators: List<String> = listOf("root"),
|
||||
val targetedEntityId: Int? = null,
|
||||
val targetLocators: List<String>? = null
|
||||
val targetLocators: List<String>? = null,
|
||||
val targetPosition: Vec3? = null
|
||||
) : NetworkPacket<SpawnSnowstormEntityParticlePacket> {
|
||||
companion object {
|
||||
val ID = cobblemonResource("spawn_snowstorm_entity_particle")
|
||||
@@ -39,7 +45,8 @@ class SpawnSnowstormEntityParticlePacket(
|
||||
val sourceLocators = buffer.readList { buffer.readString() }
|
||||
val targetedEntityId = buffer.readNullable { it.readInt() }
|
||||
val targetLocators = buffer.readNullable { buffer.readList { buffer.readString() }}
|
||||
return SpawnSnowstormEntityParticlePacket(effectId, sourceEntityId, sourceLocators, targetedEntityId, targetLocators)
|
||||
val targetPosition = buffer.readNullable { Vec3(it.readDouble(), it.readDouble(), it.readDouble()) }
|
||||
return SpawnSnowstormEntityParticlePacket(effectId, sourceEntityId, sourceLocators, targetedEntityId, targetLocators, targetPosition)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,5 +62,10 @@ class SpawnSnowstormEntityParticlePacket(
|
||||
buffer.writeString(locator)
|
||||
}
|
||||
}
|
||||
buffer.writeNullable(targetPosition) { _, value ->
|
||||
buffer.writeDouble(value.x)
|
||||
buffer.writeDouble(value.y)
|
||||
buffer.writeDouble(value.z)
|
||||
}
|
||||
}
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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.pokemon.update
|
||||
|
||||
import com.cobblemon.mod.common.net.IntSize
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.readSizedInt
|
||||
import com.cobblemon.mod.common.util.writeSizedInt
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
/**
|
||||
* Packet that adds a single skill cooldown to a Pokémon's skill cooldowns map.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since August 31st, 2025
|
||||
*/
|
||||
class SkillCooldownsUpdatePacket(
|
||||
pokemon: () -> Pokemon?,
|
||||
val skillId: ResourceLocation,
|
||||
val cooldownTicks: Int
|
||||
) : SingleUpdatePacket<Pair<ResourceLocation, Int>, SkillCooldownsUpdatePacket>(pokemon, skillId to cooldownTicks) {
|
||||
override val id: ResourceLocation = ID
|
||||
|
||||
override fun encodeValue(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeResourceLocation(skillId)
|
||||
buffer.writeSizedInt(IntSize.U_SHORT, cooldownTicks)
|
||||
}
|
||||
|
||||
override fun set(pokemon: Pokemon, value: Pair<ResourceLocation, Int>) {
|
||||
val (skillId, cooldownTicks) = value
|
||||
pokemon.skillCooldownsTicks[skillId] = cooldownTicks
|
||||
}
|
||||
|
||||
companion object {
|
||||
val ID = cobblemonResource("skill_cooldowns_update")
|
||||
fun decode(buffer: RegistryFriendlyByteBuf): SkillCooldownsUpdatePacket {
|
||||
val pokemon = decodePokemon(buffer)
|
||||
val skillId = buffer.readResourceLocation()
|
||||
val cooldownTicks = buffer.readSizedInt(IntSize.U_SHORT)
|
||||
return SkillCooldownsUpdatePacket(pokemon, skillId, cooldownTicks)
|
||||
}
|
||||
}
|
||||
}
|
||||
-9
@@ -64,7 +64,6 @@ class SpawnPokemonPacket(
|
||||
var rideStamina: Float,
|
||||
var isAlpha: Boolean,
|
||||
var silent: Boolean,
|
||||
var riders: List<Int>,
|
||||
vanillaSpawnPacket: ClientboundAddEntityPacket,
|
||||
) : SpawnExtraDataEntityPacket<SpawnPokemonPacket, PokemonEntity>(vanillaSpawnPacket) {
|
||||
|
||||
@@ -99,7 +98,6 @@ class SpawnPokemonPacket(
|
||||
entity.entityData.get(PokemonEntity.RIDE_STAMINA),
|
||||
entity.entityData.get(PokemonEntity.IS_ALPHA),
|
||||
entity.isSilent,
|
||||
entity.occupiedSeats.map { entry -> entry.value.id }.toList(),
|
||||
vanillaSpawnPacket
|
||||
)
|
||||
|
||||
@@ -136,7 +134,6 @@ class SpawnPokemonPacket(
|
||||
buffer.writeFloat(rideStamina)
|
||||
buffer.writeBoolean(isAlpha)
|
||||
buffer.writeBoolean(silent)
|
||||
buffer.writeCollection(this.riders) { pb, value -> pb.writeInt(value) }
|
||||
}
|
||||
|
||||
override fun applyData(entity: PokemonEntity, level: ClientLevel) {
|
||||
@@ -187,10 +184,6 @@ class SpawnPokemonPacket(
|
||||
|
||||
entity.tickSpawned = this.tickSpawned
|
||||
entity.delegate.updateAge(this.tickSpawned)
|
||||
|
||||
if (this.riders.isNotEmpty()) {
|
||||
this.riders.forEach { level.getEntity(it)?.startRiding(entity) }
|
||||
}
|
||||
}
|
||||
|
||||
override fun checkType(entity: Entity): Boolean = entity is PokemonEntity
|
||||
@@ -229,7 +222,6 @@ class SpawnPokemonPacket(
|
||||
val rideStamina = buffer.readFloat()
|
||||
val isAlpha = buffer.readBoolean()
|
||||
val silent = buffer.readBoolean()
|
||||
val riders = buffer.readList { it.readInt() }.toList()
|
||||
val vanillaPacket = decodeVanillaPacket(buffer)
|
||||
|
||||
return SpawnPokemonPacket(
|
||||
@@ -261,7 +253,6 @@ class SpawnPokemonPacket(
|
||||
rideStamina,
|
||||
isAlpha,
|
||||
silent,
|
||||
riders,
|
||||
vanillaPacket
|
||||
)
|
||||
}
|
||||
|
||||
-33
@@ -1,33 +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.net.messages.client.ui
|
||||
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.api.tms.TechnicalMachine
|
||||
import com.cobblemon.mod.common.api.tms.TechnicalMachines
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
|
||||
class SynchronizeActiveTMPacket(val tm: TechnicalMachine?): NetworkPacket<SynchronizeActiveTMPacket> {
|
||||
override val id = ID
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeNullable(tm?.id) { pb, value -> pb.writeResourceLocation(value) }
|
||||
}
|
||||
|
||||
companion object {
|
||||
val ID = cobblemonResource("synchronize_active_tm")
|
||||
fun decode(buffer: RegistryFriendlyByteBuf): SynchronizeActiveTMPacket {
|
||||
val resourceLocation = buffer.readNullable { it.readResourceLocation() }
|
||||
if (resourceLocation == null) return SynchronizeActiveTMPacket(null)
|
||||
val tm = TechnicalMachines.tmMap[resourceLocation]
|
||||
return SynchronizeActiveTMPacket(tm)
|
||||
}
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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.server
|
||||
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import java.util.UUID
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
/**
|
||||
* Packet sent by the client to the server to indicate that it wants to use a Poké Skill.
|
||||
*
|
||||
* The server will validate if the skill can be used, and if so, will execute it.
|
||||
*
|
||||
* @param skillId The ID of the skill to use.
|
||||
* @param pokemonId The UUID of the Pokémon using the skill.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since August 31st, 2025
|
||||
*/
|
||||
class UsePokeSkillPacket(
|
||||
val skillId: ResourceLocation,
|
||||
val pokemonId: UUID,
|
||||
) : NetworkPacket<UsePokeSkillPacket> {
|
||||
override val id: ResourceLocation = ID
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeResourceLocation(skillId)
|
||||
buffer.writeUUID(pokemonId)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val ID = ResourceLocation("cobblemon", "use_poke_skill")
|
||||
fun decode(buffer: RegistryFriendlyByteBuf): UsePokeSkillPacket {
|
||||
return UsePokeSkillPacket(
|
||||
buffer.readResourceLocation(),
|
||||
buffer.readUUID()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.net.serverhandling
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonPokeSkills
|
||||
import com.cobblemon.mod.common.api.net.ServerNetworkPacketHandler
|
||||
import com.cobblemon.mod.common.net.messages.server.UsePokeSkillPacket
|
||||
import com.cobblemon.mod.common.util.party
|
||||
import net.minecraft.server.MinecraftServer
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
object UsePokeSkillHandler : ServerNetworkPacketHandler<UsePokeSkillPacket> {
|
||||
override fun handle(packet: UsePokeSkillPacket, server: MinecraftServer, player: ServerPlayer) {
|
||||
val party = player.party()
|
||||
val pokemon = party[packet.pokemonId] ?: return // Who?
|
||||
val skill = CobblemonPokeSkills.getAccessibleSkills(player, pokemon).firstOrNull { it.id == packet.skillId } ?: return // What skill?
|
||||
if (skill.canUse(player, pokemon)) {
|
||||
skill.use(player, pokemon)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -767,6 +767,8 @@ open class Pokemon : ShowdownIdentifiable {
|
||||
val riding: RidingProperties
|
||||
get() = this.form.riding
|
||||
|
||||
var skillCooldownsTicks: MutableMap<ResourceLocation, Int> = mutableMapOf()
|
||||
|
||||
init {
|
||||
storeCoordinates.subscribe { if (it != null && it.store !is PCStore && this.tetheringId != null) afterOnServer(seconds = 0.05F) { this.tetheringId = null } }
|
||||
storeCoordinates.subscribe {
|
||||
@@ -1141,6 +1143,16 @@ open class Pokemon : ShowdownIdentifiable {
|
||||
}
|
||||
}
|
||||
|
||||
fun tickSkillCooldowns() {
|
||||
this.skillCooldownsTicks.entries.forEach { (key, value) ->
|
||||
val newValue = value - 1
|
||||
if (newValue <= 0)
|
||||
this.skillCooldownsTicks -= key
|
||||
else
|
||||
this.skillCooldownsTicks[key] = newValue
|
||||
}
|
||||
}
|
||||
|
||||
fun isOnInteractionCooldown(group: ResourceLocation): Boolean {
|
||||
return this.interactionCooldowns.getOrDefault(group, 0) > 0
|
||||
}
|
||||
@@ -2229,6 +2241,11 @@ open class Pokemon : ShowdownIdentifiable {
|
||||
return true
|
||||
}
|
||||
|
||||
fun addSkillCooldown(skillId: ResourceLocation, cooldownTicks: Int) {
|
||||
skillCooldownsTicks[skillId] = cooldownTicks
|
||||
onChange(SkillCooldownsUpdatePacket({ this }, skillId, cooldownTicks))
|
||||
}
|
||||
|
||||
fun notify(packet: PokemonUpdatePacket<*>) {
|
||||
storeCoordinates.get()?.run { sendPacketToPlayers(store.getObservingPlayers(), packet) }
|
||||
}
|
||||
|
||||
-34
@@ -1,34 +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.pokemon.properties
|
||||
|
||||
import com.cobblemon.mod.common.api.properties.CustomPokemonPropertyType
|
||||
|
||||
object HeldItemVisibleProperty : CustomPokemonPropertyType<BooleanProperty> {
|
||||
override val keys = setOf("held_item_visible")
|
||||
override val needsKey = true
|
||||
|
||||
override fun fromString(value: String?) =
|
||||
when {
|
||||
value == null || value.lowercase() in listOf("true", "yes") -> heldItemVisible(true)
|
||||
value.lowercase() in listOf("false", "no") -> heldItemVisible(false)
|
||||
else -> null
|
||||
}
|
||||
|
||||
fun heldItemVisible(value: Boolean) = BooleanProperty(
|
||||
key = keys.first(),
|
||||
value = value,
|
||||
pokemonApplicator = { pokemon, _ -> pokemon.heldItemVisible = value },
|
||||
entityApplicator = { pokemonEntity, _ -> pokemonEntity.pokemon.heldItemVisible = value },
|
||||
pokemonMatcher = { pokemon, _ -> pokemon.heldItemVisible == value },
|
||||
entityMatcher = { pokemonEntity, _ -> pokemonEntity.pokemon.heldItemVisible == value }
|
||||
)
|
||||
|
||||
override fun examples() = setOf("yes", "no")
|
||||
}
|
||||
+1
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common.pokemon.status.statuses.persistent
|
||||
|
||||
import com.cobblemon.mod.common.pokemon.status.PersistentStatus
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
|
||||
class FrozenStatus : PersistentStatus(
|
||||
name = cobblemonResource("frozen"),
|
||||
showdownName = "frz",
|
||||
|
||||
@@ -20,6 +20,7 @@ object DataKeys {
|
||||
const val POKEMON_FRIENDSHIP = "Friendship"
|
||||
const val POKEMON_FULLNESS = "Fullness"
|
||||
const val POKEMON_INTERACTION_COOLDOWN = "InteractionCooldown"
|
||||
const val POKEMON_SKILL_COOLDOWNS = "SkillCooldowns"
|
||||
const val POKEMON_ALPHA = "Alpha"
|
||||
|
||||
const val POKEMON_IVS = "IVs"
|
||||
@@ -274,9 +275,11 @@ object DataKeys {
|
||||
// Habitat Blocks
|
||||
const val HABITAT_SPAWNING_STYLE = "SpawningStyle"
|
||||
const val HABITAT_MIMIC = "MimicId"
|
||||
const val HABITAT_PHASE_COUNT = "PhaseCount"
|
||||
const val HABITAT_PHASE_ORDER = "PhaseOrder"
|
||||
const val HABITAT_LEVEL_RANGE = "LevelRange"
|
||||
const val HABITAT_MODIFIERS = "Modifiers"
|
||||
const val HABITAT_POOL = "Pool"
|
||||
|
||||
// --- Pools
|
||||
const val HABITAT_POOL_ID = "PoolId"
|
||||
|
||||
@@ -100,10 +100,16 @@ fun ServerPlayer.didSleep(): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
fun ServerPlayer.isInBattle() = BattleRegistry.getBattleByParticipatingPlayer(this) != null
|
||||
fun Player.isInBattle() = if (this is ServerPlayer) {
|
||||
BattleRegistry.getBattleByParticipatingPlayer(this) != null
|
||||
} else {
|
||||
CobblemonClient.battle?.spectating == false
|
||||
}
|
||||
|
||||
var ServerPlayer.spawner: PlayerSpawner
|
||||
get() = (this as PlayerSpawnerAccessor).getPlayerSpawner()
|
||||
set(value) = (this as PlayerSpawnerAccessor).setPlayerSpawner(value)
|
||||
|
||||
fun ServerPlayer.getBattleState(): Pair<PokemonBattle, BattleActor>? {
|
||||
val battle = BattleRegistry.getBattleByParticipatingPlayer(this)
|
||||
if (battle != null) {
|
||||
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.util.adapters
|
||||
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectTimeline
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffects
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.google.gson.JsonDeserializationContext
|
||||
import com.google.gson.JsonDeserializer
|
||||
import com.google.gson.JsonElement
|
||||
import java.lang.reflect.Type
|
||||
|
||||
/**
|
||||
* Adapter for deserializing a reference to an [ActionEffectTimeline] from its identifier.
|
||||
*
|
||||
* @author Hiroku
|
||||
* @since August 31st, 2025
|
||||
*/
|
||||
object ActionEffectTimelineAdapter : JsonDeserializer<ActionEffectTimeline> {
|
||||
override fun deserialize(json: JsonElement, type: Type, ctx: JsonDeserializationContext): ActionEffectTimeline {
|
||||
val identifier = json.asString.asIdentifierDefaultingNamespace()
|
||||
val timeline = ActionEffects.actionEffects[identifier]
|
||||
return timeline ?: throw IllegalArgumentException("No ActionEffectTimeline found for id $identifier")
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,8 @@ package com.cobblemon.mod.common.util.codec
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.bedrockk.molang.MoLang
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.util.asExpressionLike
|
||||
import com.cobblemon.mod.common.util.getString
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.Codec.optionalField
|
||||
@@ -29,6 +31,17 @@ val EXPRESSION_CODEC = object : PrimitiveCodec<Expression> {
|
||||
}
|
||||
}
|
||||
|
||||
val EXPRESSION_LIKE_CODEC = object : PrimitiveCodec<ExpressionLike> {
|
||||
override fun <T> read(ops: DynamicOps<T>, input: T): DataResult<ExpressionLike> {
|
||||
return ops.getStringValue(input).map { it.asExpressionLike() }
|
||||
}
|
||||
|
||||
override fun <T> write(ops: DynamicOps<T>, value: ExpressionLike): T {
|
||||
return ops.createString(value.getString())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// special codec that always writes default value
|
||||
// vanilla changed the behaviour of Codec#optionalFieldOf(String, A) so that it OMITS default values when encoding
|
||||
// later on decoding it assumes no value -> default, but we want some default being encoded anyways so it can be targeted by commands
|
||||
|
||||
+7
-3
@@ -22,10 +22,12 @@ import net.minecraft.world.item.ItemStack
|
||||
import java.util.*
|
||||
|
||||
internal data class ClientPokemonP4(
|
||||
val originalTrainerFriendship: Optional<Int>
|
||||
val skillCooldownTicks: Map<ResourceLocation, Int>,
|
||||
val originalTrainerFriendship: Optional<Int>,
|
||||
) : Partial<Pokemon> {
|
||||
|
||||
override fun into(other: Pokemon): Pokemon {
|
||||
other.skillCooldownsTicks = this.skillCooldownTicks.toMutableMap()
|
||||
this.originalTrainerFriendship.ifPresent { other.originalTrainerFriendship = it }
|
||||
return other
|
||||
}
|
||||
@@ -36,11 +38,13 @@ internal data class ClientPokemonP4(
|
||||
*/
|
||||
internal val CODEC: MapCodec<ClientPokemonP4> = RecordCodecBuilder.mapCodec { instance ->
|
||||
instance.group(
|
||||
Codec.INT.optionalFieldOf(DataKeys.POKEMON_ORIGINAL_TRAINER_FRIENDSHIP).forGetter(ClientPokemonP4::originalTrainerFriendship)
|
||||
).apply(instance, ::ClientPokemonP4)
|
||||
Codec.unboundedMap(ResourceLocation.CODEC, Codec.INT).fieldOf(DataKeys.POKEMON_SKILL_COOLDOWNS).forGetter(ClientPokemonP4::skillCooldownTicks),
|
||||
Codec.INT.optionalFieldOf(DataKeys.POKEMON_ORIGINAL_TRAINER_FRIENDSHIP).forGetter(ClientPokemonP4::originalTrainerFriendship),
|
||||
).apply(instance, ::ClientPokemonP4)
|
||||
}
|
||||
|
||||
internal fun from(pokemon: Pokemon): ClientPokemonP4 = ClientPokemonP4(
|
||||
pokemon.skillCooldownsTicks,
|
||||
Optional.ofNullable(pokemon.originalTrainerFriendship)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -13,13 +13,16 @@ import com.cobblemon.mod.common.util.DataKeys
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.MapCodec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import java.util.*
|
||||
|
||||
internal data class PokemonP4(
|
||||
val originalTrainerFriendship: Optional<Int>
|
||||
val skillCooldownTicks: Map<ResourceLocation, Int>,
|
||||
val originalTrainerFriendship: Optional<Int>,
|
||||
) : Partial<Pokemon> {
|
||||
|
||||
override fun into(other: Pokemon): Pokemon {
|
||||
other.skillCooldownsTicks = this.skillCooldownTicks.toMutableMap()
|
||||
this.originalTrainerFriendship.ifPresent { other.originalTrainerFriendship = it }
|
||||
other.refreshOriginalTrainer()
|
||||
return other
|
||||
@@ -28,16 +31,20 @@ internal data class PokemonP4(
|
||||
companion object {
|
||||
internal val CODEC: MapCodec<PokemonP4> = RecordCodecBuilder.mapCodec { instance ->
|
||||
instance.group(
|
||||
Codec.INT.optionalFieldOf(DataKeys.POKEMON_ORIGINAL_TRAINER_FRIENDSHIP).forGetter(PokemonP4::originalTrainerFriendship)
|
||||
Codec.unboundedMap(ResourceLocation.CODEC, Codec.INT).optionalFieldOf(DataKeys.POKEMON_SKILL_COOLDOWNS, emptyMap<ResourceLocation, Int>()).forGetter { it.skillCooldownTicks },
|
||||
Codec.INT.optionalFieldOf(DataKeys.POKEMON_ORIGINAL_TRAINER_FRIENDSHIP).forGetter(PokemonP4::originalTrainerFriendship),
|
||||
).apply(instance) {
|
||||
skillCooldownTicks,
|
||||
originalTrainerFriendship -> PokemonP4(
|
||||
originalTrainerFriendship
|
||||
skillCooldownTicks,
|
||||
originalTrainerFriendship,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun from(pokemon: Pokemon): PokemonP4 = PokemonP4(
|
||||
Optional.ofNullable(pokemon.originalTrainerFriendship)
|
||||
pokemon.skillCooldownsTicks,
|
||||
Optional.ofNullable(pokemon.originalTrainerFriendship),
|
||||
)
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -281,7 +281,7 @@
|
||||
},
|
||||
"animation.luvdisc.ground_faint": {
|
||||
"loop": true,
|
||||
"animation_length": 3,
|
||||
"animation_length": 2.5,
|
||||
"bones": {
|
||||
"body": {
|
||||
"rotation": {
|
||||
|
||||
+2
-2
@@ -39,11 +39,11 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "locator_seat_1",
|
||||
"name": "locator_seat1",
|
||||
"parent": "thorax",
|
||||
"pivot": [0, 11, 0],
|
||||
"locators": {
|
||||
"seat_1": [0, 11, 1]
|
||||
"seat1": [0, 11, 1]
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
+1
-1
@@ -79,7 +79,7 @@
|
||||
"parent": "torso",
|
||||
"pivot": [0, 21, 3.75],
|
||||
"locators": {
|
||||
"seat_1": [0, 21, 3.75]
|
||||
"seat_2": [0, 21, 3.75]
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
+1
-1
@@ -78,7 +78,7 @@
|
||||
"parent": "torso",
|
||||
"pivot": [0, 21, 3.75],
|
||||
"locators": {
|
||||
"seat_1": [0, 21, 3.75]
|
||||
"seat_2": [0, 21, 3.75]
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
+2
-2
@@ -377,11 +377,11 @@
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "locator_seat_1",
|
||||
"name": "locator_seat1",
|
||||
"parent": "saddle",
|
||||
"pivot": [0, 23.525, 0],
|
||||
"locators": {
|
||||
"seat_1": [0, 23.525, 0]
|
||||
"seat1": [0, 23.525, 0]
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
-8
@@ -30,14 +30,6 @@
|
||||
"parent": "body_rotation",
|
||||
"pivot": [0, 8.5, 0]
|
||||
},
|
||||
{
|
||||
"name": "locator_seat_1",
|
||||
"parent": "waist_rotation",
|
||||
"pivot": [0, 36, 0],
|
||||
"locators": {
|
||||
"seat_1": [0, 35.75, 8.5]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "waist_scale",
|
||||
"parent": "waist_rotation",
|
||||
|
||||
+22
-18
@@ -188,10 +188,12 @@
|
||||
"parent": "eyes",
|
||||
"pivot": [-1.51, 13.3, -1],
|
||||
"cubes": [
|
||||
{"origin": [-1.52, 12.8, -2], "size": [0, 1, 1], "uv": [62, 15]},
|
||||
{"origin": [-1.53, 12.8, -1.5], "size": [0, 1, 3], "uv": [56, 13]},
|
||||
{"origin": [-1.51, 11.3, -2], "size": [0, 2, 3], "uv": [56, 14]},
|
||||
{"origin": [-1.52, 11.3, 0.5], "size": [0, 2, 1], "uv": [62, 16]}
|
||||
{"origin": [-1.51, 12.8, -2], "size": [0, 1, 2], "uv": [60, 14]},
|
||||
{"origin": [-1.51, 12.8, -0.5], "size": [0, 1, 2], "uv": [56, 14]},
|
||||
{"origin": [-1.51, 11.3, -2], "size": [0, 1, 2], "uv": [60, 16]},
|
||||
{"origin": [-1.51, 11.3, -0.5], "size": [0, 1, 2], "uv": [56, 16]},
|
||||
{"origin": [-1.51, 11.8, -2], "size": [0, 1, 2], "uv": [60, 15]},
|
||||
{"origin": [-1.51, 11.8, -0.5], "size": [0, 1, 2], "uv": [56, 15]}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -199,8 +201,8 @@
|
||||
"parent": "eye_right",
|
||||
"pivot": [-1.51, 13.8, -0.25],
|
||||
"cubes": [
|
||||
{"origin": [-1.53, 13.8, -1.5], "size": [0, 1, 3], "uv": [56, 12]},
|
||||
{"origin": [-1.52, 13.8, -2], "size": [0, 1, 1], "uv": [62, 14]}
|
||||
{"origin": [-1.51, 13.8, -0.5], "size": [0, 1, 2], "uv": [56, 13]},
|
||||
{"origin": [-1.51, 13.8, -2], "size": [0, 1, 2], "uv": [60, 13]}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -221,7 +223,7 @@
|
||||
"parent": "pupil_right",
|
||||
"pivot": [-1.52, 13, -0.25],
|
||||
"cubes": [
|
||||
{"origin": [-1.54, 12.5, -0.75], "size": [0, 1, 1], "uv": [1, 0]}
|
||||
{"origin": [-1.52, 12.5, -0.75], "size": [0, 1, 1], "uv": [1, 0]}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -238,7 +240,7 @@
|
||||
"parent": "pupil_right",
|
||||
"pivot": [-1.42, 13, -1.25],
|
||||
"cubes": [
|
||||
{"origin": [-1.44, 12.5, -1.75], "size": [0, 1, 1], "uv": [1, 1]}
|
||||
{"origin": [-1.42, 12.5, -1.75], "size": [0, 1, 1], "uv": [1, 1]}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -246,7 +248,7 @@
|
||||
"parent": "pupil_right",
|
||||
"pivot": [-1.42, 13, 0.75],
|
||||
"cubes": [
|
||||
{"origin": [-1.44, 12.5, 0.25], "size": [0, 1, 1], "uv": [1, 2]}
|
||||
{"origin": [-1.42, 12.5, 0.25], "size": [0, 1, 1], "uv": [1, 2]}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -270,10 +272,12 @@
|
||||
"parent": "eyes",
|
||||
"pivot": [1.51, 13.3, -1],
|
||||
"cubes": [
|
||||
{"origin": [1.52, 12.8, -2], "size": [0, 1, 1], "uv": [54, 15], "mirror": true},
|
||||
{"origin": [1.53, 12.8, -1.5], "size": [0, 1, 3], "uv": [48, 13], "mirror": true},
|
||||
{"origin": [1.51, 11.3, -2], "size": [0, 2, 3], "uv": [48, 14], "mirror": true},
|
||||
{"origin": [1.52, 11.3, 0.5], "size": [0, 2, 1], "uv": [54, 16], "mirror": true}
|
||||
{"origin": [1.51, 12.8, -2], "size": [0, 1, 2], "uv": [52, 14], "mirror": true},
|
||||
{"origin": [1.51, 12.8, -0.5], "size": [0, 1, 2], "uv": [48, 14], "mirror": true},
|
||||
{"origin": [1.51, 11.3, -2], "size": [0, 1, 2], "uv": [52, 16], "mirror": true},
|
||||
{"origin": [1.51, 11.3, -0.5], "size": [0, 1, 2], "uv": [48, 16], "mirror": true},
|
||||
{"origin": [1.51, 11.8, -2], "size": [0, 1, 2], "uv": [52, 15], "mirror": true},
|
||||
{"origin": [1.51, 11.8, -0.5], "size": [0, 1, 2], "uv": [48, 15], "mirror": true}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -281,8 +285,8 @@
|
||||
"parent": "eye_left",
|
||||
"pivot": [1.51, 13.8, -0.25],
|
||||
"cubes": [
|
||||
{"origin": [1.53, 13.8, -1.5], "size": [0, 1, 3], "uv": [48, 12], "mirror": true},
|
||||
{"origin": [1.52, 13.8, -2], "size": [0, 1, 1], "uv": [54, 14], "mirror": true}
|
||||
{"origin": [1.51, 13.8, -0.5], "size": [0, 1, 2], "uv": [48, 13], "mirror": true},
|
||||
{"origin": [1.51, 13.8, -2], "size": [0, 1, 2], "uv": [52, 13], "mirror": true}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -303,7 +307,7 @@
|
||||
"parent": "pupil_left",
|
||||
"pivot": [1.52, 13, -0.25],
|
||||
"cubes": [
|
||||
{"origin": [1.54, 12.5, -0.75], "size": [0, 1, 1], "uv": [3, 0], "mirror": true}
|
||||
{"origin": [1.52, 12.5, -0.75], "size": [0, 1, 1], "uv": [3, 0], "mirror": true}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -320,7 +324,7 @@
|
||||
"parent": "pupil_left",
|
||||
"pivot": [1.42, 13, -1.25],
|
||||
"cubes": [
|
||||
{"origin": [1.44, 12.5, -1.75], "size": [0, 1, 1], "uv": [3, 1], "mirror": true}
|
||||
{"origin": [1.42, 12.5, -1.75], "size": [0, 1, 1], "uv": [3, 1], "mirror": true}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -328,7 +332,7 @@
|
||||
"parent": "pupil_left",
|
||||
"pivot": [1.42, 13, 0.75],
|
||||
"cubes": [
|
||||
{"origin": [1.44, 12.5, 0.25], "size": [0, 1, 1], "uv": [3, 2], "mirror": true}
|
||||
{"origin": [1.42, 12.5, 0.25], "size": [0, 1, 1], "uv": [3, 2], "mirror": true}
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
+20
-16
@@ -188,10 +188,12 @@
|
||||
"parent": "eyes",
|
||||
"pivot": [-1.51, 13.3, -1],
|
||||
"cubes": [
|
||||
{"origin": [-1.52, 12.8, -2], "size": [0, 1, 1], "uv": [62, 13]},
|
||||
{"origin": [-1.53, 12.8, -1.5], "size": [0, 1, 3], "uv": [56, 11]},
|
||||
{"origin": [-1.51, 11.3, -2], "size": [0, 2, 3], "uv": [56, 12]},
|
||||
{"origin": [-1.52, 11.3, 0.5], "size": [0, 2, 1], "uv": [62, 14]}
|
||||
{"origin": [-1.51, 12.8, -2], "size": [0, 1, 2], "uv": [60, 12]},
|
||||
{"origin": [-1.51, 12.8, -0.5], "size": [0, 1, 2], "uv": [56, 12]},
|
||||
{"origin": [-1.51, 11.3, -2], "size": [0, 1, 2], "uv": [60, 14]},
|
||||
{"origin": [-1.51, 11.3, -0.5], "size": [0, 1, 2], "uv": [56, 14]},
|
||||
{"origin": [-1.51, 11.8, -2], "size": [0, 1, 2], "uv": [60, 13]},
|
||||
{"origin": [-1.51, 11.8, -0.5], "size": [0, 1, 2], "uv": [56, 13]}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -199,8 +201,8 @@
|
||||
"parent": "eye_right",
|
||||
"pivot": [-1.51, 13.8, -0.25],
|
||||
"cubes": [
|
||||
{"origin": [-1.53, 13.8, -1.5], "size": [0, 1, 3], "uv": [56, 10]},
|
||||
{"origin": [-1.52, 13.8, -2], "size": [0, 1, 1], "uv": [62, 12]}
|
||||
{"origin": [-1.51, 13.8, -0.5], "size": [0, 1, 2], "uv": [56, 11]},
|
||||
{"origin": [-1.51, 13.8, -2], "size": [0, 1, 2], "uv": [60, 11]}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -209,7 +211,7 @@
|
||||
"pivot": [-1.31, 11.6, 1.3],
|
||||
"cubes": [
|
||||
{"origin": [-1.81, 10.6, 0.3], "size": [1, 2, 2], "inflate": -0.3, "uv": [58, 17]},
|
||||
{"origin": [-1.62, 10.4, 1.5], "size": [1, 1, 1], "inflate": -0.1, "uv": [48, 19]}
|
||||
{"origin": [-1.61, 10.4, 1.5], "size": [1, 1, 1], "inflate": -0.1, "uv": [48, 19]}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -222,7 +224,7 @@
|
||||
"parent": "pupil_right",
|
||||
"pivot": [-1.52, 13, -0.25],
|
||||
"cubes": [
|
||||
{"origin": [-1.54, 12.5, -0.75], "size": [0, 1, 1], "uv": [1, 0]}
|
||||
{"origin": [-1.52, 12.5, -0.75], "size": [0, 1, 1], "uv": [1, 0]}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -255,10 +257,12 @@
|
||||
"parent": "eyes",
|
||||
"pivot": [1.51, 13.3, -1],
|
||||
"cubes": [
|
||||
{"origin": [1.52, 12.8, -2], "size": [0, 1, 1], "uv": [54, 13], "mirror": true},
|
||||
{"origin": [1.53, 12.8, -1.5], "size": [0, 1, 3], "uv": [48, 11], "mirror": true},
|
||||
{"origin": [1.51, 11.3, -2], "size": [0, 2, 3], "uv": [48, 12], "mirror": true},
|
||||
{"origin": [1.52, 11.3, 0.5], "size": [0, 2, 1], "uv": [54, 14], "mirror": true}
|
||||
{"origin": [1.51, 12.8, -2], "size": [0, 1, 2], "uv": [52, 12], "mirror": true},
|
||||
{"origin": [1.51, 12.8, -0.5], "size": [0, 1, 2], "uv": [48, 12], "mirror": true},
|
||||
{"origin": [1.51, 11.3, -2], "size": [0, 1, 2], "uv": [52, 14], "mirror": true},
|
||||
{"origin": [1.51, 11.3, -0.5], "size": [0, 1, 2], "uv": [48, 14], "mirror": true},
|
||||
{"origin": [1.51, 11.8, -2], "size": [0, 1, 2], "uv": [52, 13], "mirror": true},
|
||||
{"origin": [1.51, 11.8, -0.5], "size": [0, 1, 2], "uv": [48, 13], "mirror": true}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -266,8 +270,8 @@
|
||||
"parent": "eye_left",
|
||||
"pivot": [1.51, 13.8, -0.25],
|
||||
"cubes": [
|
||||
{"origin": [1.53, 13.8, -1.5], "size": [0, 1, 3], "uv": [48, 10], "mirror": true},
|
||||
{"origin": [1.52, 13.8, -2], "size": [0, 1, 1], "uv": [54, 12], "mirror": true}
|
||||
{"origin": [1.51, 13.8, -0.5], "size": [0, 1, 2], "uv": [48, 11], "mirror": true},
|
||||
{"origin": [1.51, 13.8, -2], "size": [0, 1, 2], "uv": [52, 11], "mirror": true}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -276,7 +280,7 @@
|
||||
"pivot": [1.31, 11.6, 1.3],
|
||||
"cubes": [
|
||||
{"origin": [0.81, 10.6, 0.3], "size": [1, 2, 2], "inflate": -0.3, "uv": [52, 17], "mirror": true},
|
||||
{"origin": [0.62, 10.4, 1.5], "size": [1, 1, 1], "inflate": -0.1, "uv": [48, 17], "mirror": true}
|
||||
{"origin": [0.61, 10.4, 1.5], "size": [1, 1, 1], "inflate": -0.1, "uv": [48, 17], "mirror": true}
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -289,7 +293,7 @@
|
||||
"parent": "pupil_left",
|
||||
"pivot": [1.52, 13, -0.25],
|
||||
"cubes": [
|
||||
{"origin": [1.54, 12.5, -0.75], "size": [0, 1, 1], "uv": [3, 0], "mirror": true}
|
||||
{"origin": [1.52, 12.5, -0.75], "size": [0, 1, 1], "uv": [3, 0], "mirror": true}
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
-8
@@ -274,14 +274,6 @@
|
||||
"parent": "lower_gear_rotation",
|
||||
"pivot": [0, 9, -6]
|
||||
},
|
||||
{
|
||||
"name": "locator_seat_1",
|
||||
"parent": "lower_gear_rotation",
|
||||
"pivot": [0, 10.5, -4.5],
|
||||
"locators": {
|
||||
"seat_1": [0, 10.5, -4.5]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "gear4",
|
||||
"parent": "lower_gear",
|
||||
|
||||
-8
@@ -447,14 +447,6 @@
|
||||
"cubes": [
|
||||
{"origin": [0, -24.5, -8], "size": [0, 12, 7], "uv": [98, 109]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "locator_seat_1",
|
||||
"parent": "body",
|
||||
"pivot": [0, 54, -10],
|
||||
"locators": {
|
||||
"seat_1": [0, 54, -10]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
-61
@@ -474,67 +474,6 @@
|
||||
"cubes": [
|
||||
{"origin": [27, 10.5, 5], "size": [15, 19, 0], "uv": [223, 39]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "locator_seat_1",
|
||||
"parent": "torso",
|
||||
"pivot": [0, 30, -19],
|
||||
"locators": {
|
||||
"seat_1": [0, 30, -19]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "locator_seat_2",
|
||||
"parent": "torso",
|
||||
"pivot": [13, 30, -14],
|
||||
"rotation": [0, -90, 0],
|
||||
"locators": {
|
||||
"seat_2": [13, 30, -14]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "locator_seat_3",
|
||||
"parent": "torso",
|
||||
"pivot": [-13, 30, -14],
|
||||
"rotation": [0, 90, 0],
|
||||
"locators": {
|
||||
"seat_3": [-13, 30, -14]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "locator_seat_4",
|
||||
"parent": "torso",
|
||||
"pivot": [0, 34, -3],
|
||||
"locators": {
|
||||
"seat_4": [0, 34, -3]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "locator_seat_5",
|
||||
"parent": "torso",
|
||||
"pivot": [13, 30, 2],
|
||||
"rotation": [0, -90, 0],
|
||||
"locators": {
|
||||
"seat_5": [13, 30, 2]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "locator_seat_6",
|
||||
"parent": "torso",
|
||||
"pivot": [-13, 30, 2],
|
||||
"rotation": [0, 90, 0],
|
||||
"locators": {
|
||||
"seat_6": [-13, 30, 2]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "locator_seat_7",
|
||||
"parent": "torso",
|
||||
"pivot": [0, 33, 7],
|
||||
"rotation": [0, 180, 0],
|
||||
"locators": {
|
||||
"seat_7": [0, 33, 7]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+1
-2
@@ -2,8 +2,7 @@
|
||||
"portraitScale": 1.03,
|
||||
"portraitTranslation": [-0.31, 0.12, 0],
|
||||
"profileScale": 0.47,
|
||||
"profileTranslation": [0.07, 0.98, 0.0],
|
||||
"profilePokedexTranslation": [0, 0.98, 0],
|
||||
"profileTranslation": [0, 0.98, 0.0],
|
||||
"rootBone": "venusaur",
|
||||
"firstPersonCameraOffset": {
|
||||
"seat_1": [0, 0.25, 0]
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"portraitScale": 1.89,
|
||||
"portraitTranslation": [-0.13, 0.91, 0],
|
||||
"profileScale": 0.77,
|
||||
"profileTranslation": [0, 0.65, 0],
|
||||
"profileScale": 0.63,
|
||||
"profileTranslation": [0, 0.81, 0],
|
||||
"rootBone": "charmeleon",
|
||||
"animations": {
|
||||
"cry": "q.bedrock_stateful('charmeleon', 'cry')"
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
"portraitScale": 2.1,
|
||||
"portraitTranslation": [-1.11, 2.43, 0],
|
||||
"profileScale": 0.54,
|
||||
"profileTranslation": [0, 0.92, -10],
|
||||
"profileTranslation": [0, 0.96, -10],
|
||||
"rootBone": "charizard",
|
||||
"firstPersonCameraOffset": {
|
||||
"seat_1": [0, 0.45, 0]
|
||||
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"portraitScale": 1.89,
|
||||
"portraitTranslation": [-0.8, 1.36, 0.0],
|
||||
"profileScale": 0.57,
|
||||
"profileTranslation": [0, 0.81, 0.0],
|
||||
"profileScale": 0.59,
|
||||
"profileTranslation": [0, 0.84, 0.0],
|
||||
"rootBone": "nidoking",
|
||||
"animations": {
|
||||
"cry": "q.bedrock_stateful('nidoking', 'cry')",
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
"portraitScale": 1.8,
|
||||
"portraitTranslation": [-0.35, -0.8, 0],
|
||||
"profileScale": 0.8,
|
||||
"profileTranslation": [0, 0.52, 0.0],
|
||||
"profileTranslation": [0, 0.45, 0.0],
|
||||
"rootBone": "parasect",
|
||||
"firstPersonCameraOffset": {
|
||||
"seat_1": [0, 0.45, 0]
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"portraitScale": 1.96,
|
||||
"portraitTranslation": [ -0.3, 1.86, 0],
|
||||
"portraitTranslation": [ -0.48, 1.61, 0],
|
||||
"profileScale": 0.53,
|
||||
"profileTranslation": [0, 0.92, 0],
|
||||
"rootBone": "mr_rime",
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
"portraitScale": 1.73,
|
||||
"portraitTranslation": [-0.45, -1.17, 0],
|
||||
"profileScale": 0.7,
|
||||
"profileTranslation": [0, 0.59, 0],
|
||||
"profileTranslation": [-0.06, 0.59, 0],
|
||||
"rootBone": "dunsparce",
|
||||
"animations": {
|
||||
"cry": "q.bedrock_stateful('dunsparce', 'cry')",
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
"portraitScale": 1.73,
|
||||
"portraitTranslation": [-0.09, 0.26, 0],
|
||||
"profileScale": 0.60,
|
||||
"profileTranslation": [0, 0.90, 0],
|
||||
"profileTranslation": [0.16, 0.90, 0],
|
||||
"rootBone": "beautifly",
|
||||
"poses": {
|
||||
"battle-standing": {
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
"portraitScale": 1.65,
|
||||
"portraitTranslation": [-0.10, 0.16, 0],
|
||||
"profileScale": 0.63,
|
||||
"profileTranslation": [0, 0.64, 0],
|
||||
"profileTranslation": [0.13, 0.64, 0],
|
||||
"rootBone": "dustox",
|
||||
"poses": {
|
||||
"battle-standing": {
|
||||
|
||||
+1
-3
@@ -2,9 +2,7 @@
|
||||
"portraitScale": 1.63,
|
||||
"portraitTranslation": [-1.76, 1.25, 0],
|
||||
"profileScale": 0.53,
|
||||
"profileTranslation": [0.49, 0.96, 0],
|
||||
"profilePokedexTranslation": [0, 0.96, 0],
|
||||
"profileSummaryTranslation": [-0.30, 0.87, 0],
|
||||
"profileTranslation": [-0.09, 0.92, 0],
|
||||
"rootBone": "drapion",
|
||||
"animations": {
|
||||
"cry": "q.bedrock_stateful('drapion', 'cry')"
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
"portraitScale": 1.98,
|
||||
"portraitTranslation": [-0.96, 1.39, 0],
|
||||
"profileScale": 0.59,
|
||||
"profileTranslation": [0, 0.84, 0],
|
||||
"profileTranslation": [0.13, 0.82, 0],
|
||||
"rootBone": "pyroar_female",
|
||||
"animations": {
|
||||
"cry": "q.bedrock_stateful('pyroar_female', 'cry')"
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
"portraitScale": 1.89,
|
||||
"portraitTranslation": [-1.12, 1.78, 0],
|
||||
"profileScale": 0.51,
|
||||
"profileTranslation": [0, 0.97, 0],
|
||||
"profileTranslation": [0.12, 0.94, 0],
|
||||
"rootBone": "pyroar_male",
|
||||
"animations": {
|
||||
"cry": "q.bedrock_stateful('pyroar_male', 'cry')"
|
||||
|
||||
+1
-2
@@ -2,8 +2,7 @@
|
||||
"portraitScale": 1.1,
|
||||
"portraitTranslation": [-1.2, -0.009, 0],
|
||||
"profileScale": 0.5,
|
||||
"profileTranslation": [0, 0.96, 0],
|
||||
"profileSummaryTranslation": [-0.20, 0.87, 0],
|
||||
"profileTranslation": [-0.18, 0.96, 0],
|
||||
"rootBone": "dudunsparce",
|
||||
"firstPersonCameraOffset": {
|
||||
"seat_1": [0, 0.45, 0],
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
"portraitScale": 1.1,
|
||||
"portraitTranslation": [-0.8, -0.009, 0],
|
||||
"profileScale": 0.5,
|
||||
"profileTranslation": [0, 0.96, 0],
|
||||
"profileTranslation": [-0.18, 0.96, 0],
|
||||
"rootBone": "dudunsparce",
|
||||
"firstPersonCameraOffset": {
|
||||
"seat_1": [0, 0.45, 0],
|
||||
|
||||
@@ -848,6 +848,11 @@
|
||||
"cobblemon.gender.male": "Male",
|
||||
"cobblemon.gender.genderless": "Genderless",
|
||||
"cobblemon.fossilmachine.protected": "This fossil belongs to %s!",
|
||||
|
||||
"cobblemon.poke_skill.quick_ride.name": "Quick Ride",
|
||||
"cobblemon.poke_skill.teleport.name": "Teleport",
|
||||
"cobblemon.poke_skill.iron_sense.name": "Iron Sense",
|
||||
|
||||
"itemGroup.cobblemon.blocks": "Cobblemon: Blocks",
|
||||
"itemGroup.cobblemon.utility_item": "Cobblemon: Utility Items",
|
||||
"itemGroup.cobblemon.agriculture": "Cobblemon: Agriculture",
|
||||
@@ -1137,6 +1142,7 @@
|
||||
"cobblemon.container.tm_machine": "TM Machine",
|
||||
"cobblemon.ui.edit.habitat": "Habitat Editor",
|
||||
"cobblemon.ui.edit.habitat.mimic_id": "Mimic Block ID",
|
||||
"cobblemon.ui.edit.habitat.phase_number": "Number of Phases",
|
||||
"cobblemon.ui.edit.habitat.phase_order": "Phase Order: %s",
|
||||
"cobblemon.ui.edit.habitat.level_range": "Level Range (Min - Max)",
|
||||
"cobblemon.ui.edit.habitat.mode": "Mode: %s",
|
||||
@@ -1186,7 +1192,7 @@
|
||||
"cobblemon.ui.edit.habitat.validation.species": "Species must be a valid Pokemon name.",
|
||||
"cobblemon.ui.edit.habitat.validation.weight": "Weight must be greater than 0.",
|
||||
"cobblemon.ui.edit.habitat.validation.modifiers": "Modifiers format is invalid.",
|
||||
"cobblemon.ui.edit.habitat.validation.phases_list": "Phases must use a valid format for integer ranges, e.g. 1-3 or 1, 3-5, 6.",
|
||||
"cobblemon.ui.edit.habitat.validation.phases_list": "Phases must use valid moon phases (0-7), e.g. 1-3 or 1, 3-5, 6.",
|
||||
"cobblemon.ui.edit.habitat.validation.min_light": "Min Light must be between 0 and 15.",
|
||||
"cobblemon.ui.edit.habitat.validation.max_light": "Max Light must be between 0 and 15.",
|
||||
|
||||
|
||||
@@ -9351,11 +9351,11 @@
|
||||
"cobblemon.habitat.natural_lightning_rod.name": "Pararrayos natural",
|
||||
"cobblemon.habitat.quartz_spikes.name": "Picos de Cuarzo",
|
||||
"cobblemon.subtitle.tm.use": "Máquina Técnica usada",
|
||||
"cobblemon.subtitle.block.tm_machine.craft": "Máquina MT termina de imprimir la MT",
|
||||
"cobblemon.subtitle.block.tm_machine.craft": "Máquina MT imprime MT",
|
||||
"cobblemon.subtitle.block.tm_machine.off": "Máquina MT desactivada",
|
||||
"cobblemon.subtitle.block.tm_machine.on": "Máquina MT activada",
|
||||
"cobblemon.subtitle.block.tm_machine.open": "La tapa de la Máquina MT se abre",
|
||||
"cobblemon.subtitle.block.tm_machine.close": "La tapa de la Máquina MT se cierra",
|
||||
"cobblemon.subtitle.block.tm_machine.close": "Ma tapa de la Máquina MT se cierra",
|
||||
"cobblemon.subtitle.block.tm_machine.place_disc": "MT en blanco insertada en la Máquina MT",
|
||||
"cobblemon.ui.exp.number": "+%1$s §oEXP",
|
||||
"cobblemon.config.ui.award_experience_to_fainted_pokemon": "Da Exp. a Pokémon derrotados",
|
||||
@@ -9511,9 +9511,5 @@
|
||||
"advancements.cobblemon.cook_poke_snack": "Un aroma tentador",
|
||||
"advancements.cobblemon.cook_poke_snack.description": "Hornea un Poké Señuelo, un delicioso pastel que atrae a ciertos Pokémon según las bayas que uses",
|
||||
"advancements.cobblemon.register_all_tms": "Discografía completa",
|
||||
"advancements.cobblemon.plant_tumblestone.description": "Coloca un guijarro cerca de lava o de magma para que crezca a lo largo del tiempo",
|
||||
"cobblemon.subtitle.block.tm_machine.burn_loop": "Máquina MT imprime MT",
|
||||
"cobblemon.subtitle.block.tm_machine.start": "Maquina MT empieza a imprimir MT",
|
||||
"cobblemon.subtitle.block.tm_machine.tm_insert": "MT en blanco colocada en la Máquina MT",
|
||||
"cobblemon.subtitle.block.tm_machine.tm_retrieve": "MT retirada de la Máquina MT"
|
||||
"advancements.cobblemon.plant_tumblestone.description": "Coloca un guijarro cerca de lava o de magma para que crezca a lo largo del tiempo"
|
||||
}
|
||||
@@ -1235,10 +1235,10 @@
|
||||
"cobblemon.battle.fail.healblock": "%1$sは かいふくふうじで 回復できない!",
|
||||
"cobblemon.battle.fail.darkvoid": "しかし %1$sは 使うことが できなかった!",
|
||||
"cobblemon.battle.fail.teatime": "しかし 何も 起こらなかった!",
|
||||
"cobblemon.battle.fail.slp": "しかし %1$sは 眠らない!",
|
||||
"cobblemon.battle.fail.par": "しかし %1$sは まひにならない!",
|
||||
"cobblemon.battle.fail.slp": "%1$sは すでに 眠っている",
|
||||
"cobblemon.battle.fail.par": "%1$sは すでに まひしている",
|
||||
"cobblemon.battle.fail.tox": "%1$sは すでに 毒を あびている",
|
||||
"cobblemon.battle.fail.psn": "しかし %1$sは 毒にならない!",
|
||||
"cobblemon.battle.fail.psn": "%1$sは すでに 毒を あびている",
|
||||
"cobblemon.battle.fail.brn": "%1$sは すでに やけどを 負っている",
|
||||
"cobblemon.battle.fail.frz": "%1$sは すでに 凍っている",
|
||||
"cobblemon.battle.fail.uproar": "%1$sは 騒いでいて 眠れない!",
|
||||
@@ -9302,61 +9302,5 @@
|
||||
"cobblemon.habitat.pinkflowerbed_clearing.name": "ピンクフラワーベッドの開拓地",
|
||||
"cobblemon.habitat.sandpit_clearing.name": "砂場の開拓地",
|
||||
"cobblemon.habitat.sunflowerbed_clearing.name": "ヒマワリベッドの開拓地",
|
||||
"cobblemon.habitat.sunscorched_clearing.name": "日差しに焼かれた開拓地",
|
||||
"cobblemon.habitat.quartz_spikes.name": "クォーツスパイク",
|
||||
"cobblemon.habitat.reclaimed_desert_monument.name": "再生された砂漠の記念碑",
|
||||
"cobblemon.habitat.reclaimed_lush_monument.name": "再生された繁茂した記念碑",
|
||||
"cobblemon.habitat.rocky_outcrop.name": "岩の露頭",
|
||||
"cobblemon.habitat.rocky_tide_pool.name": "岩場の潮だまり",
|
||||
"cobblemon.habitat.root_nursery.name": "根苗圃",
|
||||
"cobblemon.habitat.sandy_tide_pool.name": "砂地の潮だまり",
|
||||
"cobblemon.habitat.skeletal_fall.name": "骸骨の墓場",
|
||||
"cobblemon.habitat.snowy_burrow.name": "雪に覆われた巣穴",
|
||||
"cobblemon.habitat.snowy_grotto.name": "雪に覆われた洞窟",
|
||||
"cobblemon.habitat.snowy_thermal_vents.name": "雪に覆われた熱水噴出孔",
|
||||
"cobblemon.habitat.thermal_crevices.name": "熱の裂け目",
|
||||
"cobblemon.habitat.treasure_hoard.name": "秘宝の宝庫",
|
||||
"cobblemon.habitat.volcanic_plume.name": "火山噴出柱",
|
||||
"cobblemon.habitat.zen_garden.name": "思念の庭園",
|
||||
"cobblemon.subtitle.tm.use": "わざマシン使用済み",
|
||||
"cobblemon.subtitle.block.tm_machine.burn_loop": "わざマシンマシンでわざマシンをプリントする",
|
||||
"cobblemon.subtitle.block.tm_machine.start": "わざマシンマシンがわざマシンのプリントを開始しました",
|
||||
"cobblemon.subtitle.block.tm_machine.craft": "わざマシンマシンがわざマシンのプリントを完了しました",
|
||||
"cobblemon.subtitle.block.tm_machine.open": "わざマシンマシンの蓋が開きます",
|
||||
"cobblemon.subtitle.block.tm_machine.close": "わざマシンマシンの蓋が閉じます",
|
||||
"cobblemon.subtitle.block.tm_machine.tm_insert": "わざマシンマシンに空のわざマシンをセットする",
|
||||
"cobblemon.subtitle.block.tm_machine.tm_retrieve": "わざマシンをわざマシンマシンから入手",
|
||||
"cobblemon.subtitle.block.tm_machine.item_insert": "アイテムをわざマシンマシンに配置しました",
|
||||
"cobblemon.subtitle.block.tm_machine.item_retrieve": "わざマシンマシンからアイテムを取り出した",
|
||||
"cobblemon.ui.exp.number": "+%1$s §o経験値",
|
||||
"cobblemon.config.ui.award_experience_to_fainted_pokemon": "倒れたポケモンにも経験値を与える",
|
||||
"cobblemon.config.ui.award_experience_to_fainted_pokemon.tooltip": "バトル中ひんしになったポケモンは、ひんしになる前に倒すのに貢献した相手から経験値を獲得できるか。",
|
||||
"cobblemon.config.ui.award_experience_on_battle_loss": "戦闘敗北時の経験値",
|
||||
"cobblemon.config.ui.award_experience_on_battle_loss.tooltip": "バトルに負けた場合でも、倒した相手からポケモンは経験値を獲得できるか。ひんしになったポケモンが経験値を獲得するには、「倒れたポケモンにも経験値を与える」が有効になっている必要がある。",
|
||||
"cobblemon.config.ui.fossil_machine_alpha_chance": "化石マシンのオヤブン出現確率",
|
||||
"cobblemon.config.ui.fossil_machine_alpha_chance.tooltip": "化石マシンから入手できるポケモンがオヤブンになる確率。\"[入力した数値]分の1\"として計算される。",
|
||||
"cobblemon.config.ui.fossil_machine_shiny_chance.tooltip": "ふくげんマシンから入手できるポケモンが色違いになる確率。\"[入力した数値]分の1\"として計算される。",
|
||||
"cobblemon.config.ui.honey_slather_alpha_chance.tooltip": "ミツ塗りの木から入手できるポケモンがオヤブンになる確率。\"[入力した数値]分の1\"として計算される。",
|
||||
"cobblemon.config.ui.honey_slather_shiny_chance.tooltip": "ミツ塗りの木から入手できるポケモンが色違いになる確率。\"[入力した数値]分の1\"として計算される。",
|
||||
"cobblemon.config.ui.fossil_machine_shiny_chance": "化石マシンの色違い出現確率",
|
||||
"cobblemon.config.ui.honey_slather_alpha_chance": "ミツ塗りの木のオヤブン出現確率",
|
||||
"cobblemon.config.ui.honey_slather_shiny_chance": "ミツ塗りの木の色違い出現確率",
|
||||
"cobblemon.config.ui.data_monitor_alpha_rate": "データモニターのオヤブン出現確率",
|
||||
"cobblemon.config.ui.data_monitor_alpha_rate.tooltip": "データモニターから入手できるポケモンがオヤブンになる確率。\"[入力した数値]分の1\"として計算される。",
|
||||
"cobblemon.config.ui.data_monitor_shiny_rate": "データモニターの色違い出現確率",
|
||||
"cobblemon.config.ui.data_monitor_shiny_rate.tooltip": "データモニターから入手できるポケモンが色違いになる確率。\"[入力した数値]分の1\"として計算される。",
|
||||
"cobblemon.config.ui.pokemon_intrinsic_size_min.tooltip": "出現するポケモンの最小固有サイズ倍率。",
|
||||
"cobblemon.config.ui.pokemon_intrinsic_size_min": "ポケモンの最小固有サイズ",
|
||||
"cobblemon.config.ui.pokemon_intrinsic_size_max": "ポケモンの最大固有サイズ",
|
||||
"cobblemon.config.ui.pokemon_intrinsic_size_max.tooltip": "出現するポケモンの最大固有サイズ倍率。",
|
||||
"cobblemon.config.ui.alpha_pokemon_size_small_multiplier.tooltip": "当たり判定が0.5ブロック未満のポケモンに対するオヤブンサイズ倍率。",
|
||||
"cobblemon.config.ui.alpha_pokemon_size_small_multiplier": "小さいオヤブンサイズ倍率",
|
||||
"cobblemon.config.ui.alpha_pokemon_size_medium_multiplier": "中くらいのオヤブンサイズ倍率",
|
||||
"cobblemon.config.ui.alpha_pokemon_size_medium_multiplier.tooltip": "当たり判定が0.5ブロックから1.5ブロックの間のポケモンに対するオヤブンサイズ倍率。",
|
||||
"cobblemon.config.ui.alpha_pokemon_size_large_multiplier": "大きいオヤブンサイズ倍率",
|
||||
"cobblemon.config.ui.alpha_pokemon_size_large_multiplier.tooltip": "当たり判定が1.5ブロックから10ブロックの間のポケモンに対するオヤブンサイズ倍率。",
|
||||
"cobblemon.config.ui.alpha_pokemon_size_extra_large_multiplier.tooltip": "当たり判定が10ブロック以上のポケモンに対するオヤブンサイズ倍率。",
|
||||
"cobblemon.config.ui.alpha_pokemon_size_extra_large_multiplier": "とても大きいオヤブンサイズ倍率",
|
||||
"cobblemon.config.ui.baby_pokemon_level_duration": "ベイビィポケモン期間レベル",
|
||||
"cobblemon.config.ui.baby_pokemon_level_duration.tooltip": "ポケモンが通常よりも小さく見える「ベイビィポケモン」とみなされるレベル数。"
|
||||
"cobblemon.habitat.sunscorched_clearing.name": "日差しに焼かれた開拓地"
|
||||
}
|
||||
@@ -5936,14 +5936,14 @@
|
||||
"block.cobblemon.red_apricorn": "红球果",
|
||||
"block.cobblemon.yellow_apricorn": "黄球果",
|
||||
"block.cobblemon.lectern": "讲台",
|
||||
"cobblemon.fishing_bait_effects.nature.tooltip": "%1$s%% - %2$s↑性格出现率",
|
||||
"cobblemon.fishing_bait_effects.iv.tooltip": "%1$s%% - %2$s个体值+%3$s",
|
||||
"cobblemon.fishing_bait_effects.ev.tooltip": "%1$s%% - %2$s基础点数出现率",
|
||||
"cobblemon.fishing_bait_effects.bite_time.tooltip": "%1$s%% - 上钩时间缩短%3$s%%",
|
||||
"cobblemon.fishing_bait_effects.gender_chance.tooltip": "%1$s%% - %2$s性别出现率",
|
||||
"cobblemon.fishing_bait_effects.level_raise.tooltip": "%1$s%% - 等级+%3$s",
|
||||
"cobblemon.fishing_bait_effects.nature.tooltip": "%1$s%%-%2$s↑性格出现率",
|
||||
"cobblemon.fishing_bait_effects.iv.tooltip": "%1$s%%-%2$s个体值+%3$s",
|
||||
"cobblemon.fishing_bait_effects.ev.tooltip": "%1$s%%-%2$s基础点数出现率",
|
||||
"cobblemon.fishing_bait_effects.bite_time.tooltip": "%1$s%% - 上钩时间缩短 %3$s%%",
|
||||
"cobblemon.fishing_bait_effects.gender_chance.tooltip": "%1$s%%-%2$s性别出现率",
|
||||
"cobblemon.fishing_bait_effects.level_raise.tooltip": "%1$s%% - 等级 +%3$s",
|
||||
"cobblemon.fishing_bait_effects.tera.tooltip": "%1$s%% - 吸引 %2$s 太晶属性",
|
||||
"cobblemon.fishing_bait_effects.shiny_reroll.tooltip": "%1$s%% - 发光概率×%3$s",
|
||||
"cobblemon.fishing_bait_effects.shiny_reroll.tooltip": "%1$s%% - 异色概率 ×%3$s",
|
||||
"cobblemon.fishing_bait_effects.ha_chance.tooltip": "%1$s%% - 隐藏特性出现率",
|
||||
"cobblemon.fishing_bait_effects.pokemon_chance.tooltip": "%1$s%% - 上钩一只宝可梦",
|
||||
"cobblemon.fishing_bait_effects.friendship.tooltip": "%1$s%% - 亲密度 +%3$s",
|
||||
@@ -6179,7 +6179,7 @@
|
||||
"cobblemon.species.ironjugulis.desc": "它与超自然杂志曾报道过的宝可梦很相似。报道中的宝可梦是爱上机器人的三首恶龙所生的孩子。",
|
||||
"cobblemon.species.pecharunt.desc": "会让对手吃下能提升欲望和能力的毒粘糕,然后通过锁链控制对手。",
|
||||
"cobblemon.ability.teraformzero.desc": "太乐巴戈斯变为星晶形态时,蕴藏在它身上的力量会将天气和场地的影响全部归零。",
|
||||
"cobblemon.subtitle.pokemon.shiny_shine": "被捕获的发光宝可梦闪闪发光",
|
||||
"cobblemon.subtitle.pokemon.shiny_shine": "被捕获的异色宝可梦闪闪发光",
|
||||
"cobblemon.battle.heal.bagitemrevive": "%1$s 恢复了活力!",
|
||||
"cobblemon.battle.detailschange.noice": "%1$s的样子发生了变化!",
|
||||
"cobblemon.battle.detailschange.eiscue": "%1$s的样子发生了变化!",
|
||||
@@ -6206,9 +6206,9 @@
|
||||
"cobblemon.ability.hospitality": "款待",
|
||||
"cobblemon.ability.poisonpuppeteer": "毒傀儡",
|
||||
"cobblemon.ability.supersweetsyrup": "甘露之蜜",
|
||||
"cobblemon.subtitle.pokemon.wild_shiny_shine": "野生的发光宝可梦!",
|
||||
"cobblemon.subtitle.pokemon.owned_shiny_ambient": "周围的发光宝可梦闪闪发光",
|
||||
"cobblemon.subtitle.pokemon.shiny_ambient": "野生的发光宝可梦闪闪发光!",
|
||||
"cobblemon.subtitle.pokemon.wild_shiny_shine": "野生的异色宝可梦!",
|
||||
"cobblemon.subtitle.pokemon.owned_shiny_ambient": "周围的异色宝可梦闪闪发光",
|
||||
"cobblemon.subtitle.pokemon.shiny_ambient": "野生的异色宝可梦闪闪发光!",
|
||||
"cobblemon.battle.withdraw.self": "%1$s ,回来!",
|
||||
"cobblemon.battle.withdraw.other": "%1$s换下了%2$s!",
|
||||
"cobblemon.type.suffix": "%1$s 属性",
|
||||
@@ -6399,34 +6399,34 @@
|
||||
"cobblemon.pokerod.remove": "右键移除饵料",
|
||||
"item.cobblemon.galarica_nuts": "伽勒豆蔻枝",
|
||||
"item.cobblemon.npc_editor": "NPC的训练家证",
|
||||
"item.cobblemon.dragon_scale.tooltip": "当海刺龙携带进行连接交换时,可使其进化为刺龙王",
|
||||
"item.cobblemon.link_cable.tooltip": "可使需要连接交换的宝可梦进化",
|
||||
"item.cobblemon.dragon_scale.tooltip": "在连接交换时携带,可使海刺龙进化为刺龙王",
|
||||
"item.cobblemon.link_cable.tooltip": "使需要通过交换进化的宝可梦进化",
|
||||
"item.cobblemon.kings_rock.tooltip_2": "在交换时携带,可使蚊香君进化为蚊香蛙皇,呆呆兽进化为呆呆王",
|
||||
"item.cobblemon.metal_coat.tooltip_1": "携带后,钢属性的招式威力就会增强",
|
||||
"item.cobblemon.kings_rock.tooltip_1": "携带该道具的宝可梦造成伤害时,有概率使目标陷入畏缩状态",
|
||||
"item.cobblemon.metal_coat.tooltip_2": "在连接交换时携带,可使大岩蛇进化为大钢蛇,飞天螳螂进化为巨钳螳螂",
|
||||
"item.cobblemon.upgrade.tooltip": "当多边兽携带进行连接交换时,可使其进化为多边兽2型",
|
||||
"item.cobblemon.dubious_disc.tooltip": "当多边兽2型携带进行连接交换时,可使其进化为多边兽乙型",
|
||||
"item.cobblemon.metal_coat.tooltip_2": "在连接交换时携带,可使大岩蛇进化为大钢蛇,使飞天螳螂进化为巨钳螳螂",
|
||||
"item.cobblemon.upgrade.tooltip": "在连接交换时携带,可使多边兽进化为多边兽2型",
|
||||
"item.cobblemon.dubious_disc.tooltip": "在连接交换时携带,可使多边兽2型进化为多边兽乙型",
|
||||
"item.cobblemon.deep_sea_scale.tooltip_1": "大幅提升珍珠贝的特防",
|
||||
"item.cobblemon.deep_sea_scale.tooltip_2": "当珍珠贝携带进行连接交换时,可使其进化为樱花鱼",
|
||||
"item.cobblemon.deep_sea_tooth.tooltip_2": "当珍珠贝携带进行连接交换时,可使其进化为猎斑鱼",
|
||||
"item.cobblemon.electirizer.tooltip": "当电击兽携带进行连接交换时,可使其进化为电击魔兽",
|
||||
"item.cobblemon.magmarizer.tooltip": "当鸭嘴火兽携带进行连接交换时,可使其进化为鸭嘴炎兽",
|
||||
"item.cobblemon.oval_stone.tooltip": "当小福蛋携带并处于白天时,可使其进化为吉利蛋",
|
||||
"item.cobblemon.protector.tooltip": "当钻角犀兽携带进行连接交换时,可使其进化为超甲狂犀",
|
||||
"item.cobblemon.prism_scale.tooltip": "当丑丑鱼携带进行连接交换时,可使其进化为美纳斯",
|
||||
"item.cobblemon.sachet.tooltip": "当粉香香携带进行连接交换时,可使其进化为芳香精",
|
||||
"item.cobblemon.whipped_dream.tooltip": "当绵绵泡芙携带进行连接交换时,可使其进化为胖甜妮",
|
||||
"item.cobblemon.love_sweet.tooltip": "当小仙奶携带时,可使其进化为霜奶仙的爱心形态",
|
||||
"item.cobblemon.berry_sweet.tooltip": "当小仙奶携带时,可使其进化为霜奶仙的野莓形态",
|
||||
"item.cobblemon.flower_sweet.tooltip": "当小仙奶携带时,可使其进化为霜奶仙的花朵形态",
|
||||
"item.cobblemon.ribbon_sweet.tooltip": "当小仙奶携带时,可使其进化为霜奶仙的蝴蝶结形态",
|
||||
"item.cobblemon.cracked_pot.tooltip": "当对赝品来悲茶使用时,可使其进化为怖思壶",
|
||||
"item.cobblemon.unremarkable_teacup.tooltip": "当对斯魔茶(冒牌货的样子)使用时,可使其进化为来悲粗茶(凡作的样子)",
|
||||
"item.cobblemon.sweet_apple.tooltip": "当对啃果虫使用时,可使其进化为丰蜜龙",
|
||||
"item.cobblemon.tart_apple.tooltip": "当对啃果虫使用时,可使其进化为苹裹龙",
|
||||
"item.cobblemon.galarica_wreath.tooltip": "当对呆呆兽(伽勒尔的样子)使用时,可使其进化为呆呆王(伽勒尔的样子)",
|
||||
"item.cobblemon.black_augurite.tooltip": "当对飞天螳螂使用,可使其进化为劈斧螳螂",
|
||||
"item.cobblemon.deep_sea_scale.tooltip_2": "在连接交换时携带,可使珍珠贝进化为樱花鱼",
|
||||
"item.cobblemon.deep_sea_tooth.tooltip_2": "在连接交换时携带,可使珍珠贝进化为猎斑鱼",
|
||||
"item.cobblemon.electirizer.tooltip": "在连接交换时携带,可使电击兽进化为电击魔兽",
|
||||
"item.cobblemon.magmarizer.tooltip": "当鸭嘴火兽携带进行连接进化时,会使其进化为鸭嘴炎兽",
|
||||
"item.cobblemon.oval_stone.tooltip": "当小福蛋携带进行连接交换时,会使其进化为吉利蛋",
|
||||
"item.cobblemon.protector.tooltip": "当钻角犀兽携带进行连接交换时,会使其进化为超甲狂犀",
|
||||
"item.cobblemon.prism_scale.tooltip": "当丑丑鱼携带进行连接交换时,会使其进化为美纳斯",
|
||||
"item.cobblemon.sachet.tooltip": "当粉香香携带进行连接交换时,会使其进化为芳香精",
|
||||
"item.cobblemon.whipped_dream.tooltip": "当绵绵泡芙携带进行连接交换时,会使其进化为胖甜妮",
|
||||
"item.cobblemon.love_sweet.tooltip": "当小仙奶携带时,会使其进化为霜奶仙的爱心形态",
|
||||
"item.cobblemon.berry_sweet.tooltip": "当小仙奶携带时,会使其进化为霜奶仙的野莓形态",
|
||||
"item.cobblemon.flower_sweet.tooltip": "当小仙奶携带时,会使其进化为霜奶仙的花朵形态",
|
||||
"item.cobblemon.ribbon_sweet.tooltip": "当小仙奶携带时,会使其进化为霜奶仙的蝴蝶结形态",
|
||||
"item.cobblemon.cracked_pot.tooltip": "当对赝品来悲茶使用时,会使其进化为怖思壶",
|
||||
"item.cobblemon.unremarkable_teacup.tooltip": "当对斯魔茶(冒牌货的样子)使用时,会使其进化为来悲粗茶(凡作的样子)",
|
||||
"item.cobblemon.sweet_apple.tooltip": "当对啃果虫使用时,会使其进化为丰蜜龙",
|
||||
"item.cobblemon.tart_apple.tooltip": "当对啃果虫使用时,会使其进化为苹裹龙",
|
||||
"item.cobblemon.galarica_wreath.tooltip": "当对呆呆兽(伽勒尔的样子)使用时,会使其进化为呆呆王(伽勒尔的样子)",
|
||||
"item.cobblemon.black_augurite.tooltip": "当对飞天螳螂使用,会使其进化为劈斧螳螂",
|
||||
"item.cobblemon.moon_stone.tooltip": "进化特定宝可梦",
|
||||
"item.cobblemon.dawn_stone.tooltip": "进化特定宝可梦",
|
||||
"item.cobblemon.fire_stone.tooltip": "进化特定宝可梦",
|
||||
@@ -6480,8 +6480,8 @@
|
||||
"item.cobblemon.absorb_bulb.tooltip_2": "使用后消耗",
|
||||
"item.cobblemon.air_balloon.tooltip_1": "携带后,会浮在空中",
|
||||
"item.cobblemon.assault_vest.tooltip": "虽然携带后特防会提高,但会无法使出变化招式",
|
||||
"item.cobblemon.auspicious_armor.tooltip": "当对炭小侍使用时,可使其进化为红莲铠骑",
|
||||
"item.cobblemon.malicious_armor.tooltip": "当对炭小侍使用时,可使其进化为苍炎刃鬼",
|
||||
"item.cobblemon.auspicious_armor.tooltip": "当对炭小侍使用时,会使其进化为红莲铠骑",
|
||||
"item.cobblemon.malicious_armor.tooltip": "当对炭小侍使用时,会使其进化为苍炎刃鬼",
|
||||
"item.cobblemon.binding_band.tooltip": "携带后,绑紧招式的威力会变强",
|
||||
"item.cobblemon.black_belt.tooltip": "携带后,格斗属性的招式威力就会提高",
|
||||
"item.cobblemon.black_sludge.tooltip": "携带后,毒属性的宝可梦会缓缓回复HP。其他属性的话,HP则会减少",
|
||||
@@ -6532,7 +6532,7 @@
|
||||
"item.cobblemon.shed_shell.tooltip": "携带后,必定可以和后备的宝可梦进行替换",
|
||||
"item.cobblemon.shell_bell.tooltip": "携带后,攻击对手并造成伤害时,能回复少量HP",
|
||||
"item.cobblemon.shell_helmet": "硬壳头盔",
|
||||
"item.cobblemon.shell_helmet.tooltip": "当对盖盖虫使用时,可使其进化为骑士蜗牛",
|
||||
"item.cobblemon.shell_helmet.tooltip": "当对盖盖虫使用时,会使其进化为骑士蜗牛",
|
||||
"item.cobblemon.silver_powder.tooltip": "携带后,虫属性的招式威力就会提高",
|
||||
"item.cobblemon.soft_sand.tooltip": "携带后,地面属性的招式威力就会提高",
|
||||
"item.cobblemon.soothe_bell.tooltip": "携带后,会变得容易和训练家亲密",
|
||||
@@ -6604,13 +6604,13 @@
|
||||
"item.cobblemon.flying_gem.tooltip_1": "携带后,飞行属性的招式威力会增强一次",
|
||||
"item.cobblemon.flying_gem.tooltip_2": "使用后消耗",
|
||||
"block.cobblemon.big_root.tooltip": "携带后,吸取HP的招式可以比平时更多地回复自己的HP",
|
||||
"item.cobblemon.clover_sweet.tooltip": "当小仙奶携带时,可使其进化为霜奶仙的幸运草形态",
|
||||
"item.cobblemon.clover_sweet.tooltip": "当小仙奶携带时,会使其进化为霜奶仙的幸运草形态",
|
||||
"item.cobblemon.water_stone.tooltip": "进化特定宝可梦",
|
||||
"item.cobblemon.jolly_mint.tooltip": "当对宝可梦使用后,会使其性格影响改变为爽朗性格",
|
||||
"item.cobblemon.cell_battery.tooltip_1": "携带它的宝可梦如果受到电属性招式的伤害,攻击就会提高",
|
||||
"item.cobblemon.dragon_fang.tooltip": "携带后,龙属性的招式威力就会提高",
|
||||
"item.cobblemon.eject_button.tooltip_1": "携带它的宝可梦如果受到招式的伤害,就能逃脱战斗",
|
||||
"item.cobblemon.razor_fang.tooltip_2": "当天蝎携带在夜晚进行等级升级时,可使其进化为天蝎王",
|
||||
"item.cobblemon.razor_fang.tooltip_2": "当天蝎携带在夜晚进行等级升级时,会使其进化为天蝎王",
|
||||
"item.cobblemon.ring_target.tooltip": "携带后,原本因属性相克关系而无效的招式现在会变得能够击中自己",
|
||||
"item.cobblemon.wise_glasses.tooltip": "携带后,特殊招式的威力就会少量提高",
|
||||
"item.cobblemon.power_bracer.tooltip": "携带后,在战斗中获得经验值时,会获得8点攻击基础点数",
|
||||
@@ -6618,9 +6618,9 @@
|
||||
"item.cobblemon.x_special_defence.tooltip": "在战斗中使用时,会使目标的特防提升一级",
|
||||
"item.cobblemon.full_heal.tooltip": "治愈一只宝可梦的所有异常状态",
|
||||
"item.cobblemon.paralyze_heal.tooltip": "治愈一只宝可梦的麻痹状态",
|
||||
"item.cobblemon.reaper_cloth.tooltip": "当彷徨夜灵携带进行连接交换时,可使其进化为黑夜魔灵",
|
||||
"item.cobblemon.masterpiece_teacup.tooltip": "当对斯魔茶(高档货的样子)使用时,可使其进化为来悲粗茶(杰作的样子)",
|
||||
"item.cobblemon.galarica_cuff.tooltip": "当对呆呆兽(伽勒尔的样子)使用时,可使其进化为呆壳兽(伽勒尔的样子)",
|
||||
"item.cobblemon.reaper_cloth.tooltip": "当彷徨夜灵携带进行连接交换时,会使其进化为黑夜魔灵",
|
||||
"item.cobblemon.masterpiece_teacup.tooltip": "当对斯魔茶(高档货的样子)使用时,会使其进化为来悲粗茶(杰作的样子)",
|
||||
"item.cobblemon.galarica_cuff.tooltip": "当对呆呆兽(伽勒尔的样子)使用时,会使其进化为呆壳兽(伽勒尔的样子)",
|
||||
"item.cobblemon.ability_capsule.tooltip": "当对宝可梦使用后,会使其特性改变为另一种常见特性",
|
||||
"item.cobblemon.lonely_mint.tooltip": "当对宝可梦使用后,会使其性格影响改变为怕寂寞性格",
|
||||
"item.cobblemon.brave_mint.tooltip": "当对宝可梦使用后,会使其性格影响改变为勇敢性格",
|
||||
@@ -6636,13 +6636,13 @@
|
||||
"item.cobblemon.burn_heal.tooltip": "治愈一只宝可梦的灼伤状态",
|
||||
"item.cobblemon.dragon_gem.tooltip_2": "使用后消耗",
|
||||
"item.cobblemon.ground_gem.tooltip_1": "携带后,地面属性的招式威力会增强一次",
|
||||
"item.cobblemon.peat_block.tooltip": "当在满月对圈圈熊使用时,可使其进化为月月熊",
|
||||
"item.cobblemon.strawberry_sweet.tooltip": "当小仙奶携带时,可使其进化为霜奶仙的草莓形态",
|
||||
"item.cobblemon.chipped_pot.tooltip": "当对真品来悲茶使用时,可使其进化为怖思壶",
|
||||
"item.cobblemon.peat_block.tooltip": "当在满月对圈圈熊使用时,会使其进化为月月熊",
|
||||
"item.cobblemon.strawberry_sweet.tooltip": "当小仙奶携带时,会使其进化为霜奶仙的草莓形态",
|
||||
"item.cobblemon.chipped_pot.tooltip": "当对真品来悲茶使用时,会使其进化为怖思壶",
|
||||
"item.cobblemon.focus_band.tooltip": "携带后,即便受到可能会导致昏厥的招式,有时也能仅以1HP撑过去",
|
||||
"item.cobblemon.light_clay.tooltip": "携带后,使出像光墙和反射壁一样的保护招式时,效果会比平时持续得更长",
|
||||
"item.cobblemon.red_card.tooltip_1": "携带后,能让对自己造成伤害的对手退场",
|
||||
"item.cobblemon.medicinal_leek.tooltip_1": "可调制成药品",
|
||||
"item.cobblemon.medicinal_leek.tooltip_1": "能用来调制成药品",
|
||||
"item.cobblemon.remedy.tooltip": "使一只宝可梦回复20HP,同时小幅降低它的亲密度",
|
||||
"item.cobblemon.fine_remedy.tooltip": "使一只宝可梦回复60HP,同时小幅降低它的亲密度",
|
||||
"item.cobblemon.superb_remedy.tooltip": "使一只宝可梦回复120HP,同时小幅降低它的亲密度",
|
||||
@@ -6653,7 +6653,7 @@
|
||||
"item.cobblemon.ghost_gem.tooltip_1": "携带后,幽灵属性的招式威力会增强一次",
|
||||
"item.cobblemon.rock_gem.tooltip_1": "携带后,岩石属性的招式威力会增强一次",
|
||||
"item.cobblemon.psychic_gem.tooltip_2": "使用后消耗",
|
||||
"item.cobblemon.star_sweet.tooltip": "当小仙奶携带时,可使其进化为霜奶仙的星星形态",
|
||||
"item.cobblemon.star_sweet.tooltip": "当小仙奶携带时,会使其进化为霜奶仙的星星形态",
|
||||
"item.cobblemon.relaxed_mint.tooltip": "当对宝可梦使用后,会使其性格影响改变为悠闲性格",
|
||||
"item.cobblemon.quiet_mint.tooltip": "当对宝可梦使用后,会使其性格影响改变为冷静性格",
|
||||
"item.cobblemon.careful_mint.tooltip": "当对宝可梦使用后,会使其性格影响改变为慎重性格",
|
||||
@@ -6678,8 +6678,8 @@
|
||||
"item.cobblemon.bug_gem.tooltip_1": "携带后,虫属性的招式威力会增强一次",
|
||||
"item.cobblemon.deep_sea_tooth.tooltip_1": "大幅提升珍珠贝的特攻",
|
||||
"cobblemon.fishing.no_bite": "甚至连一口都没有。",
|
||||
"cobblemon.fishing_bait_effects.typing.tooltip": "%1$s%% - %2$s属性出现率×%3$s",
|
||||
"cobblemon.fishing_bait_effects.egg_group.tooltip": "%1$s%% - %2$s蛋群出现率×%3$s",
|
||||
"cobblemon.fishing_bait_effects.typing.tooltip": "%1$s%%-%2$s属性出现率×%3$s",
|
||||
"cobblemon.fishing_bait_effects.egg_group.tooltip": "%1$s%%-%2$s蛋群出现率×%3$s",
|
||||
"cobblemon.egg_group.monster": "怪兽",
|
||||
"cobblemon.egg_group.water_1": "水中1",
|
||||
"cobblemon.egg_group.bug": "虫",
|
||||
@@ -6712,7 +6712,7 @@
|
||||
"cobblemon.ui.interact.ride": "骑乘",
|
||||
"cobblemon.ui.interact.request_already_expired": "该请求已过期!",
|
||||
"cobblemon.ui.pokedex.search.search_by": "搜索 %1$s 中",
|
||||
"cobblemon.ui.pokedex.search.type.species": "宝可梦名称",
|
||||
"cobblemon.ui.pokedex.search.type.species": "物种名称",
|
||||
"cobblemon.ui.pokedex.search.type.abilities": "特性",
|
||||
"cobblemon.ui.pokedex.search.type.drops": "掉落物",
|
||||
"cobblemon.cosmetic.held_logs.crimson": "绯红菌柄",
|
||||
@@ -6911,10 +6911,10 @@
|
||||
"cobblemon.config.ui.display_entity_name_label": "显示宝可梦的名字",
|
||||
"cobblemon.config.ui.display_entity_level_label": "显示宝可梦的等级",
|
||||
"cobblemon.config.ui.display_entity_labels_when_crouching_only.tooltip": "控制是否只在蹲下时显示宝可梦的标签。",
|
||||
"cobblemon.config.ui.shiny_rate": "发光概率",
|
||||
"cobblemon.config.ui.shiny_rate.tooltip": "生成发光宝可梦的概率。若设为0,则发光宝可梦不会生成。该概率以1/x的形式计算。",
|
||||
"cobblemon.config.ui.shiny_notice_particles_distance": "发光粒子的显示距离",
|
||||
"cobblemon.config.ui.shiny_notice_particles_distance.tooltip": "宝可梦发光粒子效果开始显示的距离。",
|
||||
"cobblemon.config.ui.shiny_rate": "异色概率",
|
||||
"cobblemon.config.ui.shiny_rate.tooltip": "生成的宝可梦为异色的概率。若设为0,则生成的宝可梦不会出现异色。该概率以1/x的形式计算。",
|
||||
"cobblemon.config.ui.shiny_notice_particles_distance": "异色粒子的显示距离",
|
||||
"cobblemon.config.ui.shiny_notice_particles_distance.tooltip": "宝可梦异色粒子效果开始显示的距离。",
|
||||
"cobblemon.config.ui.capture_calculator": "捕获计算器",
|
||||
"cobblemon.config.ui.player_damage_pokemon": "玩家攻击宝可梦",
|
||||
"cobblemon.config.ui.player_damage_pokemon.tooltip": "控制玩家是否可以攻击一般实体一样攻击宝可梦。",
|
||||
@@ -7073,7 +7073,7 @@
|
||||
"cobblemon.battle.block.aromaveil": "%1$s 正受到芳香幕的保护!",
|
||||
"cobblemon.species.mimikyu-busted.desc": "因正身就要暴露而很悲痛。绝不原谅折断了它脖子的对手,会向对方报仇。",
|
||||
"item.cobblemon.syrupy_apple": "蜜汁苹果",
|
||||
"item.cobblemon.syrupy_apple.tooltip": "当啃果虫使用时,可使其进化为裹蜜虫",
|
||||
"item.cobblemon.syrupy_apple.tooltip": "当啃果虫使用时,会使其进化为裹蜜虫",
|
||||
"cobblemon.command.unlockablepcboxwallpaper.invalid-wallpaper": "无效的壁纸标识",
|
||||
"cobblemon.ui.pc.wallpaper": "壁纸",
|
||||
"cobblemon.ui.pc.filter": "筛选",
|
||||
@@ -8577,9 +8577,9 @@
|
||||
"cobblemon.ui.pokedex.info.form.dartrix-hisuibias": "洗翠趋异的样子",
|
||||
"block.cobblemon.potted_saccharine_sapling": "蜜露树苗盆栽",
|
||||
"item.cobblemon.saccharine_sapling": "蜜露树苗",
|
||||
"item.cobblemon.metal_alloy.tooltip": "当对铝钢龙使用时,可使其进化为铝钢桥龙",
|
||||
"item.cobblemon.metal_alloy.tooltip": "当对铝钢龙使用时,会使其进化为铝钢桥龙",
|
||||
"item.cobblemon.health_mochi": "体力粘糕",
|
||||
"item.cobblemon.scroll_of_waters.tooltip": "当对熊徒弟使用时,可使其进化为武道熊师(连击流)",
|
||||
"item.cobblemon.scroll_of_waters.tooltip": "当对熊徒弟使用时,会使其进化为武道熊师(连击流)",
|
||||
"item.cobblemon.potato_mochi": "马铃薯粘糕",
|
||||
"item.cobblemon.aprijuice_black": "黑球果汁",
|
||||
"item.cobblemon.health_mochi.tooltip": "提升宝可梦的HP基础点数4点",
|
||||
@@ -8592,7 +8592,7 @@
|
||||
"item.cobblemon.metal_alloy": "复合金属",
|
||||
"item.cobblemon.scroll_of_darkness": "恶之挂轴",
|
||||
"item.cobblemon.scroll_of_waters": "水之挂轴",
|
||||
"item.cobblemon.scroll_of_darkness.tooltip": "当对熊徒弟使用时,可使其进化为武道熊师(一击流)",
|
||||
"item.cobblemon.scroll_of_darkness.tooltip": "当对熊徒弟使用时,会使其进化为武道熊师(一击流)",
|
||||
"item.cobblemon.fried_rice": "炒饭",
|
||||
"item.cobblemon.candied_apple": "蜜饯苹果",
|
||||
"item.cobblemon.moomoo_milk": "哞哞鲜奶",
|
||||
@@ -8673,13 +8673,13 @@
|
||||
"item.cobblemon.ponigiri": "宝可饭团",
|
||||
"item.cobblemon.poke_puff.frosted": "珍奇 %s 宝芙蕾",
|
||||
"tooltip.cobblemon.poke_puff.nature.neutral": "中性",
|
||||
"item.cobblemon.health_candy.tooltip_1": "提升宝可梦的HP有效个体值1点",
|
||||
"item.cobblemon.brittle_candy.tooltip_1": "降低宝可梦的防御有效个体值1点",
|
||||
"item.cobblemon.numb_candy.tooltip_1": "降低宝可梦的特攻有效个体值1点",
|
||||
"item.cobblemon.health_candy.tooltip_1": "提升宝可梦HP的有效个体值1点",
|
||||
"item.cobblemon.brittle_candy.tooltip_1": "降低宝可梦防御的有效个体值1点",
|
||||
"item.cobblemon.numb_candy.tooltip_1": "降低宝可梦特攻的有效个体值1点",
|
||||
"cobblemon.ui.info.gender": "性别",
|
||||
"item.cobblemon.courage_candy.tooltip_1": "提升宝可梦的特防有效个体值1点",
|
||||
"item.cobblemon.courage_candy.tooltip_1": "提升宝可梦特防的有效个体值1点",
|
||||
"cobblemon.command.behaviouredit.non_scriptable": "您并没有看着一个可执行MoLang脚本的实体。",
|
||||
"cobblemon.command.pcsearch.tooltip.shiny": "这只是发光宝可梦!",
|
||||
"cobblemon.command.pcsearch.tooltip.shiny": "这只宝可梦已经是异色了!",
|
||||
"cobblemon.command.pcsearch.entry": "- %1$s %2$s",
|
||||
"block.cobblemon.campfire": "营火",
|
||||
"block.cobblemon.campfire_pot_black": "黑色营火锅",
|
||||
@@ -8711,20 +8711,20 @@
|
||||
"cobblemon.tooltip.poke_puff.friendship_effects": "亲密度影响",
|
||||
"item.cobblemon.health_candy": "元气糖果",
|
||||
"item.cobblemon.mighty_candy": "力量糖果",
|
||||
"item.cobblemon.mighty_candy.tooltip_1": "提升宝可梦的攻击有效个体值1点",
|
||||
"item.cobblemon.mighty_candy.tooltip_1": "提升宝可梦攻击的有效个体值1点",
|
||||
"item.cobblemon.tough_candy": "守护糖果",
|
||||
"item.cobblemon.tough_candy.tooltip_1": "提升宝可梦的防御有效个体值1点",
|
||||
"item.cobblemon.tough_candy.tooltip_1": "提升宝可梦防御的有效个体值1点",
|
||||
"item.cobblemon.smart_candy": "知识糖果",
|
||||
"item.cobblemon.smart_candy.tooltip_1": "提升宝可梦的特攻有效个体值1点",
|
||||
"item.cobblemon.smart_candy.tooltip_1": "提升宝可梦特攻的有效个体值1点",
|
||||
"item.cobblemon.courage_candy": "心灵糖果",
|
||||
"item.cobblemon.quick_candy": "敏捷糖果",
|
||||
"item.cobblemon.quick_candy.tooltip_1": "提升宝可梦的速度有效个体值1点",
|
||||
"item.cobblemon.quick_candy.tooltip_1": "提升宝可梦速度的有效个体值1点",
|
||||
"item.cobblemon.sickly_candy": "虚弱糖果",
|
||||
"item.cobblemon.sickly_candy.tooltip_1": "降低宝可梦的HP有效个体值1点",
|
||||
"item.cobblemon.weak_candy.tooltip_1": "降低宝可梦的攻击有效个体值1点",
|
||||
"item.cobblemon.sickly_candy.tooltip_1": "降低宝可梦HP的有效个体值1点",
|
||||
"item.cobblemon.weak_candy.tooltip_1": "降低宝可梦攻击的有效个体值1点",
|
||||
"item.cobblemon.weak_candy": "软弱糖果",
|
||||
"item.cobblemon.coward_candy.tooltip_1": "降低宝可梦的特防有效个体值1点",
|
||||
"item.cobblemon.slow_candy.tooltip_1": "降低宝可梦的速度有效个体值1点",
|
||||
"item.cobblemon.coward_candy.tooltip_1": "降低宝可梦特防的有效个体值1点",
|
||||
"item.cobblemon.slow_candy.tooltip_1": "降低宝可梦速度的有效个体值1点",
|
||||
"item.cobblemon.brittle_candy": "脆弱糖果",
|
||||
"item.cobblemon.numb_candy": "迟钝糖果",
|
||||
"item.cobblemon.coward_candy": "胆怯糖果",
|
||||
@@ -9106,7 +9106,7 @@
|
||||
"item.cobblemon.eggant_berry": "子茄果",
|
||||
"cobblemon.entity.variable.look_at_entity_types.desc": "该实体将看向的实体类型。",
|
||||
"cobblemon.entity.variable.look_at_entity_types.name": "看向实体类型",
|
||||
"cobblemon.fishing_bait_effects.drops_reroll.tooltip": "%1$s%% - %3$s×额外掉落",
|
||||
"cobblemon.fishing_bait_effects.drops_reroll.tooltip": "%1$s%% - %3$s× 额外掉落",
|
||||
"cobblemon.requires_debug_keys": "必须在服务器上启用调试键才能使用此功能。",
|
||||
"cobblemon.ui.stats.blocks_traveled": "步数",
|
||||
"cobblemon.requires_permission": "你没有执行此操作的权限。",
|
||||
@@ -9213,125 +9213,5 @@
|
||||
"cobblemon.behaviour.defend_owner.desc": "在主人受到攻击时保护他们。",
|
||||
"stat.cobblemon.riding_land": "骑着宝可梦在陆地移动距离",
|
||||
"stat.cobblemon.riding_air": "骑着宝可梦在空中移动距离",
|
||||
"stat.cobblemon.riding_liquid": "骑着宝可梦在水域移动距离",
|
||||
"item.cobblemon.sweet_heart.tooltip": "非常甜腻的巧克力",
|
||||
"item.cobblemon.sweet_heart": "心形甜点",
|
||||
"item.cobblemon.technical_machine": "招式学习器",
|
||||
"item.cobblemon.blank_tm": "空白招式学习器",
|
||||
"block.cobblemon.deepslate_crystal_core": "深层水晶母岩",
|
||||
"block.cobblemon.normal_gem_block": "一般宝石块",
|
||||
"block.cobblemon.fire_gem_block": "火之宝石块",
|
||||
"block.cobblemon.water_gem_block": "水之宝石块",
|
||||
"block.cobblemon.electric_gem_block": "草之宝石块",
|
||||
"block.cobblemon.grass_gem_block": "电之宝石块",
|
||||
"block.cobblemon.ice_gem_block": "冰之宝石块",
|
||||
"block.cobblemon.fighting_gem_block": "格斗宝石块",
|
||||
"block.cobblemon.poison_gem_block": "毒之宝石块",
|
||||
"block.cobblemon.ground_gem_block": "地面宝石块",
|
||||
"block.cobblemon.flying_gem_block": "飞行宝石块",
|
||||
"block.cobblemon.psychic_gem_block": "超能力宝石块",
|
||||
"block.cobblemon.bug_gem_block": "虫之宝石块",
|
||||
"block.cobblemon.rock_gem_block": "岩石宝石块",
|
||||
"block.cobblemon.ghost_gem_block": "幽灵宝石块",
|
||||
"block.cobblemon.dragon_gem_block": "龙之宝石块",
|
||||
"block.cobblemon.dark_gem_block": "恶之宝石块",
|
||||
"block.cobblemon.steel_gem_block": "钢之宝石块",
|
||||
"block.cobblemon.fairy_gem_block": "妖精宝石块",
|
||||
"block.cobblemon.normal_gem_cluster": "一般宝石簇",
|
||||
"block.cobblemon.fire_gem_cluster": "火之宝石簇",
|
||||
"block.cobblemon.water_gem_cluster": "水之宝石簇",
|
||||
"block.cobblemon.electric_gem_cluster": "电之宝石簇",
|
||||
"block.cobblemon.grass_gem_cluster": "草之宝石簇",
|
||||
"block.cobblemon.ice_gem_cluster": "冰之宝石簇",
|
||||
"block.cobblemon.fighting_gem_cluster": "格斗宝石簇",
|
||||
"block.cobblemon.poison_gem_cluster": "毒之宝石簇",
|
||||
"block.cobblemon.ground_gem_cluster": "地面宝石簇",
|
||||
"block.cobblemon.flying_gem_cluster": "飞行宝石簇",
|
||||
"block.cobblemon.psychic_gem_cluster": "超能力宝石簇",
|
||||
"block.cobblemon.bug_gem_cluster": "虫之宝石簇",
|
||||
"block.cobblemon.rock_gem_cluster": "岩石宝石簇",
|
||||
"block.cobblemon.ghost_gem_cluster": "幽灵宝石簇",
|
||||
"block.cobblemon.dragon_gem_cluster": "龙之宝石簇",
|
||||
"block.cobblemon.dark_gem_cluster": "恶之宝石簇",
|
||||
"block.cobblemon.steel_gem_cluster": "钢之宝石簇",
|
||||
"block.cobblemon.fairy_gem_cluster": "妖精宝石簇",
|
||||
"cobblemon.item_class.technical_machine": "招式学习器",
|
||||
"block.cobblemon.damaged_monitor": "损坏的数据显示器",
|
||||
"block.cobblemon.tm_machine": "招式学习器机",
|
||||
"block.cobblemon.disc_shelf": "唱片架",
|
||||
"cobblemon.fishing_bait_effects.mark_chance.tooltip": "%1$s%% - 证章出现率+%3$s%%",
|
||||
"cobblemon.fishing_bait_effects.alpha_chance.tooltip": "%1$s%% - 头目宝可梦出现率",
|
||||
"cobblemon.fishing_bait_effects.size.tooltip": "%1$s%% - 体型%3$s%%",
|
||||
"cobblemon.technical_machine_effect_header": "招式学习器机信息:",
|
||||
"cobblemon.command.technicalmachine.invalid-tm": "无效招式学习器",
|
||||
"cobblemon.ui.generic.question_marks": "???",
|
||||
"cobblemon.container.tm_machine": "招式学习器机",
|
||||
"cobblemon.ui.edit.habitat": "栖息地编辑器",
|
||||
"cobblemon.ui.edit.habitat.mimic_id": "模仿方块ID",
|
||||
"cobblemon.ui.edit.habitat.level_range": "等级范围(最小—最大)",
|
||||
"cobblemon.ui.edit.habitat.mode": "模式:%s",
|
||||
"cobblemon.ui.edit.habitat.mode.activated": "已激活",
|
||||
"cobblemon.ui.edit.habitat.mode.natural": "自然",
|
||||
"cobblemon.ui.edit.habitat.trigger": "触发器:%s",
|
||||
"cobblemon.ui.edit.habitat.phase_number": "阶段数",
|
||||
"cobblemon.ui.edit.habitat.phase_order": "阶段顺序:%s",
|
||||
"cobblemon.ui.edit.habitat.spawn_range": "生成范围(方块数)",
|
||||
"cobblemon.ui.edit.habitat.cancelled_range": "取消自然生成的范围(方块数)",
|
||||
"cobblemon.ui.edit.habitat.max_spawns": "最大生成数量(-1为无限)",
|
||||
"cobblemon.ui.edit.habitat.replace_spawns": "替换正常生成:%s",
|
||||
"cobblemon.ui.edit.habitat.influence_range": "影响范围(方块数)",
|
||||
"cobblemon.ui.edit.habitat.pool": "生成池:%s",
|
||||
"cobblemon.ui.edit.habitat.pool.custom": "自定义",
|
||||
"cobblemon.ui.edit.habitat.view_pool": "查看生成池",
|
||||
"cobblemon.ui.edit.habitat.edit_pool": "编辑生成池",
|
||||
"cobblemon.ui.edit.habitat.pool.title": "生成池编辑器",
|
||||
"cobblemon.ui.edit.habitat.pool.species": "宝可梦",
|
||||
"cobblemon.ui.edit.habitat.spawn.species_name": "宝可梦名称",
|
||||
"cobblemon.ui.edit.habitat.pool.levels": "等级",
|
||||
"cobblemon.ui.edit.habitat.pool.phases": "阶段",
|
||||
"cobblemon.ui.edit.habitat.pool.position": "位置",
|
||||
"cobblemon.ui.edit.habitat.pool.weight": "权重",
|
||||
"cobblemon.ui.edit.habitat.pool.bucket": "稀有度档位",
|
||||
"cobblemon.ui.edit.habitat.pool.add_spawn": "增加生成",
|
||||
"cobblemon.ui.edit.habitat.pool.back": "返回",
|
||||
"cobblemon.ui.edit.habitat.pool.select": "选择生成池",
|
||||
"cobblemon.ui.edit.habitat.spawn": "生成编辑器",
|
||||
"cobblemon.ui.edit.habitat.spawn.position_type": "位置类型:%s",
|
||||
"cobblemon.ui.edit.habitat.spawn.bucket": "稀有度档位:%s",
|
||||
"cobblemon.ui.edit.habitat.spawn.weight": "权重",
|
||||
"cobblemon.ui.edit.habitat.spawn.level_range": "等级范围(最小—最大)",
|
||||
"cobblemon.ui.edit.habitat.spawn.modifiers": "修饰词(例如:shiny gender=male)",
|
||||
"cobblemon.ui.edit.habitat.spawn.phases": "阶段(例如:1-3, 5)",
|
||||
"cobblemon.ui.edit.habitat.spawn.time_of_day": "时段",
|
||||
"cobblemon.ui.edit.habitat.spawn.time_of_day.value": "时段:%s",
|
||||
"cobblemon.ui.edit.habitat.spawn.time_of_day.any": "所有",
|
||||
"cobblemon.ui.edit.habitat.spawn.min_light": "最低光照度(0-15,可选)",
|
||||
"cobblemon.ui.edit.habitat.spawn.max_light": "最高光照度(0-15, 可选)",
|
||||
"cobblemon.ui.edit.habitat.spawn.back": "返回",
|
||||
"cobblemon.ui.edit.habitat.validation.mimic": "模仿方块必须是被允许且有效的方块ID(查看 habitat_mimics.json)。",
|
||||
"cobblemon.ui.edit.habitat.validation.phases": "阶段数必须大于0。",
|
||||
"cobblemon.ui.edit.habitat.validation.level_range": "等级范围必须处于1到100之间,且最小值不能大于最大值。",
|
||||
"cobblemon.ui.edit.habitat.validation.spawn_range": "生成范围必须为0或更高。",
|
||||
"cobblemon.ui.edit.habitat.validation.cancelled_range": "被取消的自然生成范围必须为 -1(不取消)或在 0 到 64 之间。",
|
||||
"cobblemon.ui.edit.habitat.validation.max_spawns": "最大生成数必须是-1或更高。",
|
||||
"cobblemon.ui.edit.habitat.validation.influence_range": "影响范围必须为0或更高。",
|
||||
"cobblemon.ui.edit.habitat.validation.species": "必须为一个有效的宝可梦。",
|
||||
"cobblemon.ui.edit.habitat.validation.weight": "权重必须大于0。",
|
||||
"cobblemon.ui.edit.habitat.validation.modifiers": "修饰词的格式无效。",
|
||||
"cobblemon.ui.edit.habitat.validation.min_light": "最低光照度必须处于0到15之间。",
|
||||
"cobblemon.ui.edit.habitat.validation.max_light": "最高光照度必须处于0到15之间。",
|
||||
"cobblemon.ui.moves.learnset.tm.discovered": "发现了",
|
||||
"cobblemon.ui.moves.level": "等级提升",
|
||||
"cobblemon.ui.moves.egg": "蛋",
|
||||
"cobblemon.ui.moves.tm": "招式学习器",
|
||||
"cobblemon.ui.tm_machine.can_learn": "能学习",
|
||||
"cobblemon.ui.tm_machine.cannot_learn": "不能学",
|
||||
"cobblemon.ui.tm_machine.learned": "已学会",
|
||||
"cobblemon.tms.unknown_move": "未知招式",
|
||||
"cobblemon.tms.already_known": "%1$s 已经学会了 %2$s!",
|
||||
"cobblemon.tms.teach_move": "%1$s 学会了 %2$s!",
|
||||
"cobblemon.tms.cannot_learn": "%1$s 不能学习 %2$s!",
|
||||
"cobblemon.tms.unlock_tm": "你解锁了 %1$s 招式学习器!",
|
||||
"cobblemon.tms.new_tms_learned": "学会了新的招式学习器!",
|
||||
"cobblemon.tms.check_tmm": "查看招式学习器机"
|
||||
"stat.cobblemon.riding_liquid": "骑着宝可梦在水域移动距离"
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 320 B After Width: | Height: | Size: 317 B |
Loaded 100 of 131 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user