mirror of
https://gitlab.com/cable-mc/cobblemon.git
synced 2026-10-21 22:56:23 -04:00
Compare commits
18
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
874d1d9329 | ||
|
|
d29e688064 | ||
|
|
b6802069d8 | ||
|
|
a4b8aafa27 | ||
|
|
c46a4d5936 | ||
|
|
c3c57f3f33 | ||
|
|
0dba1e9f82 | ||
|
|
41457d8da8 | ||
|
|
a8db098652 | ||
|
|
1f241fc8dc | ||
|
|
3921295fee | ||
|
|
790e5e6c8b | ||
|
|
2957cabf86 | ||
|
|
6909c5ad6f | ||
|
|
c65d6bd83e | ||
|
|
dd6a526a49 | ||
|
|
b30b03fffd | ||
|
|
1953538db5 |
+1
-16
@@ -2,7 +2,6 @@
|
||||
## [1.7.0 (Month xth, 2025)](#1-7-0)
|
||||
|
||||
### Additions
|
||||
- Added `/npcdelete` uuid parameter support and usuable to console
|
||||
- Added `/spectateBattle <player>` command to spectate battles without having to manually walk up to the target.
|
||||
- Added an in-game configuration screen, allowing all settings from `main.json` to be edited directly in-game.
|
||||
- Added `/cobblemonconfig reload` command to reload `main.json` configuration. **Note:** Some settings require a server restart to take effect; use this command cautiously.
|
||||
@@ -458,6 +457,7 @@
|
||||
- MoLang `run_action_effect` now works on Pokémon.
|
||||
- Changed MoLang entity function `is_standing_on` to allow for block tags in the list.
|
||||
- Added entity (as `q.entity`) that executed the command to the `executemolangscript` command.
|
||||
- A wild Pokémon using Teleport now ends the battle and causes the Pokémon to teleport a short distance away. Teleport still behaves the same in PvP battles.
|
||||
- Refactored the following events to `.Pre` and `.Post` for consistency:
|
||||
- `PokemonSentEvent`
|
||||
- `ExperienceGainedEvent`
|
||||
@@ -550,7 +550,6 @@
|
||||
- Fixed busted abilities and moves in Pokémon data due to removed datapacks etc. causing storage corruption. It now just rerolls their ability / uses Tackle.
|
||||
- Fixed singular Pokémon corruption causing entire storage corruption. Storages will now skip corrupted Pokémon and print an error to console.
|
||||
- Fixed species additions not being able to properly mark a species as implemented.
|
||||
- Fixed Pokémon item models not showing a glint when enchanted.
|
||||
|
||||
### Developer
|
||||
- A finished battle now has winners and losers set inside of `PokemonBattle` instead of them always being empty.
|
||||
@@ -681,20 +680,6 @@
|
||||
- Added `q.pokemon.is_busy` Returns whether the Pokémon is busy.
|
||||
- Added `q.pokemon.is_rideable` Returns whether the Pokémon is rideable.
|
||||
- Fixed `background` field and added `textColor` field for dialogues.
|
||||
- Added support to reload some data registries:
|
||||
- MoLang scripts
|
||||
- Callbacks
|
||||
- Spawn Detail Presets
|
||||
- Spawn Pools
|
||||
- Spawn Rules
|
||||
- Cosmetic Items
|
||||
- Dialogues
|
||||
- Fossils
|
||||
- Natural Materials
|
||||
- Action Effects
|
||||
- Mechanics
|
||||
- Unlockable Wallpapers
|
||||
- Starter Data
|
||||
|
||||
### Particles
|
||||
Added new/updated particles for the following moves:
|
||||
|
||||
@@ -117,8 +117,6 @@ public abstract class MouseHandlerMixin {
|
||||
@Local(argsOnly = true) double d,
|
||||
@Local(argsOnly = true) double movementTime
|
||||
) {
|
||||
boolean returnValue = true;
|
||||
|
||||
PokedexUsageContext usageContext = CobblemonClient.INSTANCE.getPokedexUsageContext();
|
||||
if (usageContext.getScanningGuiOpen()) {
|
||||
this.smoothTurnY.reset();
|
||||
@@ -129,7 +127,7 @@ public abstract class MouseHandlerMixin {
|
||||
var sensitivity = Mth.lerp(usageContext.getFovMultiplier(), spyglassSensitivity, lookSensitivity);
|
||||
var yRotationFlip = this.minecraft.options.invertYMouse().get() ? -1 : 1;
|
||||
player.turn(this.accumulatedDX * sensitivity, (this.accumulatedDY * sensitivity * yRotationFlip));
|
||||
returnValue = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Clamp player rotation if riding and the vehicle demands it
|
||||
@@ -145,7 +143,7 @@ public abstract class MouseHandlerMixin {
|
||||
pitchSmoother.reset();
|
||||
rollSmoother.reset();
|
||||
yawSmoother.reset();
|
||||
return returnValue;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Send mouse input to be interpreted into rotation
|
||||
|
||||
+4
-3
@@ -10,7 +10,8 @@ package com.cobblemon.mod.common.mixin.client.snapshots;
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonBuildDetails;
|
||||
import com.cobblemon.mod.common.client.gui.snapshots.SnapshotWarningScreen;
|
||||
import com.cobblemon.mod.common.client.persisted.ClientPersistedData;
|
||||
import com.cobblemon.mod.common.client.snapshots.SnapshotAcknowledgementData;
|
||||
import com.cobblemon.mod.common.client.snapshots.SnapshotAcknowledgementReader;
|
||||
import kotlin.Unit;
|
||||
import net.minecraft.SharedConstants;
|
||||
import net.minecraft.client.Minecraft;
|
||||
@@ -41,7 +42,7 @@ public final class SnapshotWarningMixin {
|
||||
return Unit.INSTANCE;
|
||||
}
|
||||
|
||||
ClientPersistedData.INSTANCE.writeSnapshotsData(new ClientPersistedData.SnapshotAcknowledgementData(CobblemonBuildDetails.VERSION, dsa));
|
||||
SnapshotAcknowledgementReader.INSTANCE.write(new SnapshotAcknowledgementData(CobblemonBuildDetails.VERSION, dsa));
|
||||
|
||||
runnable.run();
|
||||
return Unit.INSTANCE;
|
||||
@@ -53,7 +54,7 @@ public final class SnapshotWarningMixin {
|
||||
@Unique
|
||||
@SuppressWarnings("ResultOfMethodCallIgnored")
|
||||
private boolean cobblemon$isAcknowledged() {
|
||||
ClientPersistedData.SnapshotAcknowledgementData data = ClientPersistedData.INSTANCE.readSnapshotsData();
|
||||
SnapshotAcknowledgementData data = SnapshotAcknowledgementReader.INSTANCE.read();
|
||||
if (data == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -213,7 +213,7 @@ object CobblemonBlocks : PlatformRegistry<Registry<Block>, ResourceKey<Registry<
|
||||
@JvmField
|
||||
val SACCHARINE_SIGN = this.create("saccharine_sign", CobblemonSignBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.OAK_SIGN), SACCHARINE_WOOD_TYPE))
|
||||
@JvmField
|
||||
val SACCHARINE_WALL_SIGN = this.create("saccharine_wall_sign", CobblemonWallSignBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.OAK_SIGN), SACCHARINE_WOOD_TYPE))
|
||||
val SACCHARINE_WALL_SIGN = this.create("saccharine_wall_sign", CobblemonWallSignBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.OAK_WALL_SIGN), SACCHARINE_WOOD_TYPE))
|
||||
@JvmField
|
||||
val SACCHARINE_HANGING_SIGN = this.create("saccharine_hanging_sign", CobblemonHangingSignBlock(BlockBehaviour.Properties.ofFullCopy(Blocks.OAK_WALL_HANGING_SIGN), SACCHARINE_WOOD_TYPE))
|
||||
@JvmField
|
||||
|
||||
@@ -39,7 +39,6 @@ object CobblemonMechanics : DataRegistry {
|
||||
var potions = PotionsMechanic()
|
||||
|
||||
override fun sync(player: ServerPlayer) {}
|
||||
|
||||
override fun reload(manager: ResourceManager) {
|
||||
remedies = loadMechanic(manager, "remedies", RemediesMechanic::class.java)
|
||||
berries = loadMechanic(manager, "berries", BerriesMechanic::class.java)
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
package com.cobblemon.mod.common
|
||||
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.client.net.CalculateSeatPositionsHandler
|
||||
import com.cobblemon.mod.common.client.net.OpenBehaviourEditorHandler
|
||||
import com.cobblemon.mod.common.client.net.CalculateSeatPositionsHandler
|
||||
import com.cobblemon.mod.common.client.net.PlayerInteractOptionsHandler
|
||||
import com.cobblemon.mod.common.client.net.SetClientPlayerDataHandler
|
||||
import com.cobblemon.mod.common.client.net.animation.PlayPosableAnimationHandler
|
||||
@@ -20,7 +20,7 @@ import com.cobblemon.mod.common.client.net.callback.party.OpenPartyCallbackHandl
|
||||
import com.cobblemon.mod.common.client.net.callback.partymove.OpenPartyMoveCallbackHandler
|
||||
import com.cobblemon.mod.common.client.net.cooking.ToggleCookingPotLidHandler
|
||||
import com.cobblemon.mod.common.client.net.data.DataRegistrySyncPacketHandler
|
||||
import com.cobblemon.mod.common.client.net.data.RideSettingsSyncHandler
|
||||
import com.cobblemon.mod.common.client.net.data.UnlockReloadPacketHandler
|
||||
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
|
||||
@@ -65,8 +65,8 @@ 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.net.PacketRegisterInfo
|
||||
import com.cobblemon.mod.common.net.messages.client.CalculateSeatPositionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.OpenBehaviourEditorPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.CalculateSeatPositionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.PlayerInteractOptionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.SetClientPlayerDataPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.animation.PlayPosableAnimationPacket
|
||||
@@ -171,11 +171,11 @@ 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.SetActiveMarkPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetMarkingsPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.ServerboundUpdateRidingStatePacket
|
||||
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
|
||||
@@ -224,11 +224,11 @@ 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.SetActiveMarkHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetMarkingsHandler
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.ServerboundUpdateRidingStateHandler
|
||||
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.starter.RequestStarterScreenHandler
|
||||
@@ -312,7 +312,6 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(MarksPotentialUpdatePacket.ID, MarksPotentialUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
list.add(PacketRegisterInfo(MarkingsUpdatePacket.ID, MarkingsUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
list.add(PacketRegisterInfo(RideBoostsUpdatePacket.ID, RideBoostsUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
list.add(PacketRegisterInfo(RideStaminaUpdatePacket.ID, RideStaminaUpdatePacket::decode, PokemonUpdatePacketHandler()))
|
||||
|
||||
// Evolution start
|
||||
list.add(PacketRegisterInfo(AddEvolutionPacket.ID, AddEvolutionPacket::decode, PokemonUpdatePacketHandler()))
|
||||
@@ -391,6 +390,7 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(BerryRegistrySyncPacket.ID, BerryRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(SpeciesRegistrySyncPacket.ID, SpeciesRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(PropertiesCompletionRegistrySyncPacket.ID, PropertiesCompletionRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(UnlockReloadPacket.ID, UnlockReloadPacket::decode, UnlockReloadPacketHandler))
|
||||
list.add(PacketRegisterInfo(StandardSpeciesFeatureSyncPacket.ID, StandardSpeciesFeatureSyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(GlobalSpeciesFeatureSyncPacket.ID, GlobalSpeciesFeatureSyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(SpeciesFeatureAssignmentSyncPacket.ID, SpeciesFeatureAssignmentSyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
@@ -407,7 +407,6 @@ object CobblemonNetwork {
|
||||
list.add(PacketRegisterInfo(CosmeticItemAssignmentSyncPacket.ID, CosmeticItemAssignmentSyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(BehaviourSyncPacket.ID, BehaviourSyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(MarkRegistrySyncPacket.ID, MarkRegistrySyncPacket::decode, DataRegistrySyncPacketHandler()))
|
||||
list.add(PacketRegisterInfo(RideSettingsSyncPacket.ID, RideSettingsSyncPacket::decode, RideSettingsSyncHandler))
|
||||
|
||||
// Effects
|
||||
list.add(PacketRegisterInfo(SpawnSnowstormParticlePacket.ID, SpawnSnowstormParticlePacket::decode, SpawnSnowstormParticleHandler))
|
||||
|
||||
@@ -1,106 +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
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.cobblemon.mod.common.CobblemonNetwork.sendPacket
|
||||
import com.cobblemon.mod.common.api.data.DataRegistry
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.reactive.SimpleObservable
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviourSettings
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.types.air.BirdSettings
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.types.air.GliderSettings
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.types.air.HelicopterSettings
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.types.air.HoverSettings
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.types.air.JetSettings
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.types.air.RocketSettings
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.types.land.HorseSettings
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.types.land.MinekartSettings
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.types.land.VehicleSettings
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.types.liquid.BoatSettings
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.types.liquid.BurstSettings
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.types.liquid.DolphinSettings
|
||||
import com.cobblemon.mod.common.net.messages.client.data.RideSettingsSyncPacket
|
||||
import com.cobblemon.mod.common.util.adapters.ExpressionAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.ExpressionLikeAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.FloatNumberRangeAdapter
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.google.gson.GsonBuilder
|
||||
import net.minecraft.advancements.critereon.MinMaxBounds
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.packs.PackType
|
||||
import net.minecraft.server.packs.resources.ResourceManager
|
||||
|
||||
object CobblemonRideSettings : DataRegistry {
|
||||
override val id: ResourceLocation = cobblemonResource("ride_settings")
|
||||
override val type = PackType.SERVER_DATA
|
||||
override val observable = SimpleObservable<CobblemonRideSettings>()
|
||||
val gson = GsonBuilder()
|
||||
.setPrettyPrinting()
|
||||
.registerTypeAdapter(Expression::class.java, ExpressionAdapter)
|
||||
.registerTypeAdapter(ExpressionLike::class.java, ExpressionLikeAdapter)
|
||||
.registerTypeAdapter(MinMaxBounds.Doubles::class.java, FloatNumberRangeAdapter)
|
||||
.create()
|
||||
|
||||
var bird = BirdSettings()
|
||||
var glider = GliderSettings()
|
||||
var helicopter = HelicopterSettings()
|
||||
var hover = HoverSettings()
|
||||
var jet = JetSettings()
|
||||
var rocket = RocketSettings()
|
||||
|
||||
var horse = HorseSettings()
|
||||
var minekart = MinekartSettings()
|
||||
var vehicle = VehicleSettings()
|
||||
|
||||
var boat = BoatSettings()
|
||||
var burst = BurstSettings()
|
||||
var dolphin = DolphinSettings()
|
||||
|
||||
override fun sync(player: ServerPlayer) {
|
||||
player.sendPacket(
|
||||
RideSettingsSyncPacket(
|
||||
bird = bird,
|
||||
glider = glider,
|
||||
helicopter = helicopter,
|
||||
hover = hover,
|
||||
jet = jet,
|
||||
rocket = rocket,
|
||||
horse = horse,
|
||||
minekart = minekart,
|
||||
vehicle = vehicle,
|
||||
boat = boat,
|
||||
burst = burst,
|
||||
dolphin = dolphin
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override fun reload(manager: ResourceManager) {
|
||||
bird = loadStyle(manager, "bird", BirdSettings::class.java)
|
||||
glider = loadStyle(manager, "glider", GliderSettings::class.java)
|
||||
helicopter = loadStyle(manager, "helicopter", HelicopterSettings::class.java)
|
||||
hover = loadStyle(manager, "hover", HoverSettings::class.java)
|
||||
jet = loadStyle(manager, "jet", JetSettings::class.java)
|
||||
rocket = loadStyle(manager, "rocket", RocketSettings::class.java)
|
||||
horse = loadStyle(manager, "horse", HorseSettings::class.java)
|
||||
minekart = loadStyle(manager, "minekart", MinekartSettings::class.java)
|
||||
vehicle = loadStyle(manager, "vehicle", VehicleSettings::class.java)
|
||||
boat = loadStyle(manager, "boat", BoatSettings::class.java)
|
||||
burst = loadStyle(manager, "burst", BurstSettings::class.java)
|
||||
dolphin = loadStyle(manager, "dolphin", DolphinSettings::class.java)
|
||||
}
|
||||
|
||||
private fun <T : RidingBehaviourSettings> loadStyle(manager: ResourceManager, name: String, clazz: Class<T>): T {
|
||||
manager.getResourceOrThrow(cobblemonResource("ride_settings/$name.json")).open().use {
|
||||
return gson.fromJson(it.reader(), clazz)
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -53,7 +53,7 @@ class FindAirTaskConfig : SingleTaskConfig {
|
||||
it.absent(CobblemonMemories.PATH_COOLDOWN)
|
||||
).apply(it) { walkTarget, pathCooldown ->
|
||||
Trigger { world, entity, time ->
|
||||
if (!entity.getIsSubmerged() || entity.isInLava) {
|
||||
if (!entity.getIsSubmerged()) {
|
||||
return@Trigger false
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -57,7 +57,7 @@ class GoToLandTaskConfig : SingleTaskConfig {
|
||||
it.absent(CobblemonMemories.PATH_COOLDOWN)
|
||||
).apply(it) { walkTarget, pathCooldown ->
|
||||
Trigger { world, entity, time ->
|
||||
if (!entity.isInWater) {
|
||||
if (!entity.isInLiquid) {
|
||||
return@Trigger false
|
||||
}
|
||||
|
||||
|
||||
+24
-52
@@ -14,8 +14,6 @@ import com.cobblemon.mod.common.api.ai.CobblemonWanderControl
|
||||
import com.cobblemon.mod.common.api.ai.ExpressionOrEntityVariable
|
||||
import com.cobblemon.mod.common.api.ai.asVariables
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
import com.cobblemon.mod.common.entity.OmniPathingEntity
|
||||
import com.cobblemon.mod.common.entity.ai.CobblemonRandomSurfacePos
|
||||
import com.cobblemon.mod.common.entity.ai.CobblemonWalkTarget
|
||||
import com.cobblemon.mod.common.util.asExpression
|
||||
import com.cobblemon.mod.common.util.mainThreadRuntime
|
||||
@@ -28,7 +26,6 @@ import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.PathfinderMob
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorUtils
|
||||
import net.minecraft.world.entity.ai.behavior.BlockPosTracker
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
|
||||
@@ -44,27 +41,24 @@ class WanderTaskConfig : SingleTaskConfig {
|
||||
}
|
||||
|
||||
val condition = booleanVariable(WANDER, "wanders", true).asExpressible()
|
||||
val wanderChance = numberVariable(WANDER, "wander_chance", 1 / (20 * 6F)).asExpressible()
|
||||
val wanderChance = numberVariable(WANDER, "wander_chance", 1/(20 * 6F)).asExpressible()
|
||||
val horizontalRange = numberVariable(WANDER, "horizontal_wander_range", 10).asExpressible()
|
||||
val verticalRange = numberVariable(WANDER, "vertical_wander_range", 5).asExpressible()
|
||||
val speedMultiplier =
|
||||
numberVariable(SharedEntityVariables.MOVEMENT_CATEGORY, SharedEntityVariables.WALK_SPEED, 0.35).asExpressible()
|
||||
val avoidTargetingAir: ExpressionOrEntityVariable =
|
||||
Either.left("true".asExpression()) // Whether to avoid air blocks when wandering
|
||||
val speedMultiplier = numberVariable(SharedEntityVariables.MOVEMENT_CATEGORY, SharedEntityVariables.WALK_SPEED, 0.35).asExpressible()
|
||||
val avoidTargetingAir: ExpressionOrEntityVariable = Either.left("true".asExpression()) // Whether to avoid air blocks when wandering
|
||||
val minimumHeight: ExpressionOrEntityVariable = Either.left("0".asExpression()) // Height off the ground
|
||||
val maximumHeight: ExpressionOrEntityVariable = Either.left("-1".asExpression()) // Height off the ground
|
||||
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) =
|
||||
listOf(
|
||||
condition,
|
||||
wanderChance,
|
||||
horizontalRange,
|
||||
verticalRange,
|
||||
speedMultiplier,
|
||||
avoidTargetingAir,
|
||||
minimumHeight,
|
||||
maximumHeight
|
||||
).asVariables()
|
||||
override fun getVariables(entity: LivingEntity, behaviourConfigurationContext: BehaviourConfigurationContext) = listOf(
|
||||
condition,
|
||||
wanderChance,
|
||||
horizontalRange,
|
||||
verticalRange,
|
||||
speedMultiplier,
|
||||
avoidTargetingAir,
|
||||
minimumHeight,
|
||||
maximumHeight
|
||||
).asVariables()
|
||||
|
||||
private fun applyHeightConstraints(
|
||||
pos: BlockPos,
|
||||
@@ -83,7 +77,7 @@ class WanderTaskConfig : SingleTaskConfig {
|
||||
(1..MAX_LOOK_DOWN_DISTANCE).firstOrNull {
|
||||
val newPos = pos.below(it)
|
||||
if (!world.getBlockState(newPos).isAir) {
|
||||
return@firstOrNull true
|
||||
return@firstOrNull true
|
||||
} else if (newPos.y <= world.minBuildHeight) {
|
||||
// Don't adjust downward into the void (Mostly if we're in the end)
|
||||
// This doesn't stop fliers from wandering off end islands,
|
||||
@@ -132,7 +126,7 @@ class WanderTaskConfig : SingleTaskConfig {
|
||||
it.registered(CobblemonMemories.WANDER_CONTROL)
|
||||
).apply(it) { walkTarget, lookTarget, pathCooldown, wanderControl ->
|
||||
Trigger { world, entity, time ->
|
||||
if (entity !is PathfinderMob || (entity.isUnderWater && !(entity.canBreatheUnderwater() && !((entity as OmniPathingEntity).canSwimInWater())))) {
|
||||
if (entity !is PathfinderMob || entity.isUnderWater) {
|
||||
return@Trigger false
|
||||
}
|
||||
|
||||
@@ -140,9 +134,10 @@ class WanderTaskConfig : SingleTaskConfig {
|
||||
mainThreadRuntime.withQueryValue("entity", entity.asMostSpecificMoLangValue())
|
||||
val avoidsTargetingAir = avoidTargetingAir.resolveBoolean(mainThreadRuntime)
|
||||
val wanderChance = mainThreadRuntime.resolveFloat(wanderChanceExpression)
|
||||
if (wanderChance <= 0 || world.random.nextFloat() > wanderChance) {
|
||||
if (wanderChance <= 0 || world.random.nextFloat() > wanderChance || !wanderControl.allowLand) {
|
||||
return@Trigger false
|
||||
}
|
||||
|
||||
pathCooldown.setWithExpiry(true, wanderControl.pathCooldownTicks.toLong())
|
||||
val minimumHeight = minimumHeight.resolveInt(mainThreadRuntime)
|
||||
val maximumHeight = maximumHeight.resolveInt(mainThreadRuntime)
|
||||
@@ -162,28 +157,14 @@ class WanderTaskConfig : SingleTaskConfig {
|
||||
maximumHeight,
|
||||
minimumHeight
|
||||
)
|
||||
} else if (entity.isUnderWater && entity.canBreatheUnderwater() && !((entity as OmniPathingEntity).canSwimInWater())) {
|
||||
BehaviorUtils.getRandomSwimmablePos(
|
||||
entity,
|
||||
horizontalRange.resolveInt(mainThreadRuntime),
|
||||
verticalRange.resolveInt(mainThreadRuntime)
|
||||
)
|
||||
} else if (entity is OmniPathingEntity && (entity.canWalkOnWater() || entity.canWalkOnLava())) {
|
||||
CobblemonRandomSurfacePos.getPos(
|
||||
entity,
|
||||
horizontalRange.resolveInt(mainThreadRuntime),
|
||||
verticalRange.resolveInt(mainThreadRuntime)
|
||||
)
|
||||
} else {
|
||||
LandRandomPos.getPos(
|
||||
entity,
|
||||
horizontalRange.resolveInt(mainThreadRuntime),
|
||||
verticalRange.resolveInt(mainThreadRuntime)
|
||||
)
|
||||
LandRandomPos.getPos(
|
||||
entity,
|
||||
horizontalRange.resolveInt(mainThreadRuntime),
|
||||
verticalRange.resolveInt(mainThreadRuntime)
|
||||
)
|
||||
} ?: continue
|
||||
|
||||
if (targetVec == null) continue
|
||||
|
||||
pos = applyHeightConstraints(
|
||||
pos = BlockPos.containing(targetVec),
|
||||
minimumHeight = minimumHeight,
|
||||
@@ -201,17 +182,8 @@ class WanderTaskConfig : SingleTaskConfig {
|
||||
pos = pos,
|
||||
speedModifier = speedMultiplier.resolveFloat(mainThreadRuntime),
|
||||
completionRange = 0,
|
||||
nodeTypeFilter = { nodeType ->
|
||||
entity.canBreatheUnderwater() || nodeType !in listOf(
|
||||
PathType.WATER,
|
||||
PathType.WATER_BORDER
|
||||
)
|
||||
},
|
||||
destinationNodeTypeFilter = { nodeType ->
|
||||
!avoidsTargetingAir || nodeType !in listOf(
|
||||
PathType.OPEN
|
||||
)
|
||||
}
|
||||
nodeTypeFilter = { nodeType -> nodeType !in listOf(PathType.WATER, PathType.WATER_BORDER) },
|
||||
destinationNodeTypeFilter = { nodeType -> !avoidsTargetingAir || nodeType !in listOf(PathType.OPEN) }
|
||||
)
|
||||
)
|
||||
lookTarget.set(BlockPosTracker(pos.toVec3d().add(0.0, entity.eyeHeight.toDouble(), 0.0)))
|
||||
|
||||
-29
@@ -31,10 +31,8 @@ import net.minecraft.world.entity.ai.behavior.BlockPosTracker
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.BehaviorBuilder
|
||||
import net.minecraft.world.entity.ai.behavior.declarative.Trigger
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType
|
||||
import net.minecraft.world.level.material.Fluids
|
||||
import net.minecraft.world.level.pathfinder.PathType
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import kotlin.math.ceil
|
||||
|
||||
class WaterWanderTaskConfig : SingleTaskConfig {
|
||||
val condition = booleanVariable(WANDER, "water_wanders", true).asExpressible()
|
||||
@@ -102,33 +100,6 @@ class WaterWanderTaskConfig : SingleTaskConfig {
|
||||
return@Trigger false
|
||||
}
|
||||
|
||||
// Move target pos down so that we don't move out of water too much
|
||||
val requiredDepth = ceil(0.5 + entity.eyeHeight)
|
||||
// Get the current depth of the block
|
||||
var depth = 1
|
||||
var testPos = pos.above()
|
||||
var blockState = entity.level().getBlockState(testPos)
|
||||
while (blockState.fluidState.type == Fluids.WATER) {
|
||||
depth++
|
||||
testPos = testPos!!.above()
|
||||
blockState = entity.level().getBlockState(testPos)
|
||||
}
|
||||
|
||||
if (depth < requiredDepth) {
|
||||
// Iterate down until we reach the desired min depth or we reach a non water block
|
||||
pos = pos.below()
|
||||
blockState = entity.level().getBlockState(pos)
|
||||
while (blockState.fluidState.type == Fluids.WATER && depth < requiredDepth) {
|
||||
depth ++
|
||||
pos = pos!!.below()
|
||||
blockState = entity.level().getBlockState(pos)
|
||||
}
|
||||
}
|
||||
|
||||
if (depth < requiredDepth) {
|
||||
return@Trigger false
|
||||
}
|
||||
|
||||
walkTarget.set(
|
||||
CobblemonWalkTarget(
|
||||
pos = pos,
|
||||
|
||||
@@ -219,6 +219,7 @@ open class PokemonBattle(
|
||||
}
|
||||
|
||||
fun broadcastChatMessage(component: Component) {
|
||||
if (ended) {return}
|
||||
chatLog.add(component)
|
||||
sendSpectatorUpdate(BattleMessagePacket(component))
|
||||
return actors.forEach { it.sendMessage(component) }
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.cooking
|
||||
|
||||
import net.minecraft.ChatFormatting
|
||||
import net.minecraft.util.StringRepresentable
|
||||
|
||||
/**
|
||||
@@ -17,16 +18,16 @@ import net.minecraft.util.StringRepresentable
|
||||
* @author Licious
|
||||
* @since November 28th, 2022
|
||||
*/
|
||||
enum class Flavour(val colour: Int): StringRepresentable {
|
||||
SPICY(0xFA795E),
|
||||
DRY(0x65AFF3),
|
||||
SWEET(0xFF82CF),
|
||||
BITTER(0x77C96A),
|
||||
SOUR(0xF3D465),
|
||||
MILD(0x9D99BF);
|
||||
enum class Flavour(val colour: Int, val chatFormatting: ChatFormatting): StringRepresentable {
|
||||
SPICY(0x00FF00, ChatFormatting.RED),
|
||||
DRY(0xFF0000, ChatFormatting.DARK_AQUA),
|
||||
SWEET(0x0000FF, ChatFormatting.LIGHT_PURPLE),
|
||||
BITTER(0xFFFF00, ChatFormatting.GREEN),
|
||||
SOUR(0xFF00FF, ChatFormatting.YELLOW),
|
||||
MILD(0xFF00FF, ChatFormatting.DARK_PURPLE);
|
||||
|
||||
override fun getSerializedName() = name
|
||||
companion object {
|
||||
val CODEC = StringRepresentable.fromEnum<Flavour> { Flavour.entries.toTypedArray() }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,11 +9,13 @@
|
||||
package com.cobblemon.mod.common.api.cooking
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonItemComponents
|
||||
import com.cobblemon.mod.common.item.PokePuffItem
|
||||
import com.cobblemon.mod.common.item.PokePuffItem.Companion.DISLIKED_FLAVOR_MULTIPLIER
|
||||
import com.cobblemon.mod.common.item.PokePuffItem.Companion.LIKED_FLAVOR_MULTIPLIER
|
||||
import com.cobblemon.mod.common.pokemon.Nature
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.core.registries.BuiltInRegistries
|
||||
|
||||
object PokePuffUtils {
|
||||
|
||||
@@ -23,12 +25,11 @@ object PokePuffUtils {
|
||||
|
||||
val (baseFriendship) = calculateBaseFriendship(stack)
|
||||
|
||||
val multiplier = if (
|
||||
dominantFlavour == nature.favouriteFlavour ||
|
||||
(dominantFlavour == Flavour.MILD && isNeutralNature)
|
||||
) LIKED_FLAVOR_MULTIPLIER else -DISLIKED_FLAVOR_MULTIPLIER
|
||||
|
||||
return (baseFriendship / multiplier).toInt()
|
||||
return when {
|
||||
dominantFlavour == nature.favouriteFlavour -> (baseFriendship / LIKED_FLAVOR_MULTIPLIER).toInt()
|
||||
dominantFlavour == Flavour.MILD && isNeutralNature -> (baseFriendship / 2.0).coerceAtLeast(1.0).toInt()
|
||||
else -> (-baseFriendship / DISLIKED_FLAVOR_MULTIPLIER).toInt()
|
||||
}
|
||||
}
|
||||
|
||||
fun calculateBaseFriendship(stack: ItemStack): Pair<Double, Double> {
|
||||
@@ -76,8 +77,8 @@ object PokePuffUtils {
|
||||
Flavour.SPICY -> "attack"
|
||||
Flavour.DRY -> "special_attack"
|
||||
Flavour.SWEET -> "speed"
|
||||
Flavour.BITTER -> "special_defence"
|
||||
Flavour.SOUR -> "defence"
|
||||
Flavour.BITTER -> "special_defense"
|
||||
Flavour.SOUR -> "defense"
|
||||
Flavour.MILD -> "neutral"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,13 +18,14 @@ import net.minecraft.resources.ResourceLocation
|
||||
* @since August 5th, 2022
|
||||
*/
|
||||
interface DataProvider {
|
||||
|
||||
/**
|
||||
* Registers a [DataRegistry] to listen for updates.
|
||||
* The updates will automatically happen on the correct sides based on [DataRegistry.type].
|
||||
*
|
||||
* @param registry The [DataRegistry] being registered.
|
||||
*/
|
||||
fun <T : DataRegistry> register(registry: T, reloadable: Boolean): T
|
||||
fun <T : DataRegistry> register(registry: T): T
|
||||
|
||||
/**
|
||||
* Attempts to find a [DataRegistry] with the given [ResourceLocation].
|
||||
|
||||
@@ -152,9 +152,6 @@ object CobblemonEvents {
|
||||
@JvmField
|
||||
val RIDE_EVENT_PRE = CancelableObservable<RidePokemonEvent.Pre>()
|
||||
|
||||
@JvmField
|
||||
val RIDE_EVENT_APPLY_STAMINA = EventObservable<RidePokemonEvent.ApplyStamina>()
|
||||
|
||||
@JvmField
|
||||
val RIDE_EVENT_POST = EventObservable<RidePokemonEvent.Post>()
|
||||
|
||||
|
||||
+2
-32
@@ -8,7 +8,9 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.events.pokemon
|
||||
|
||||
import com.cobblemon.mod.common.util.server
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.cobblemon.mod.common.api.events.Cancelable
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.moLangFunctionMap
|
||||
@@ -47,36 +49,4 @@ interface RidePokemonEvent {
|
||||
"pokemon" to pokemon.struct
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Event published when stamina is being applied. At this point you can modify the stamina that will get used on the
|
||||
* mount or you can make the stamina infinite. Handy hey.
|
||||
*/
|
||||
class ApplyStamina(
|
||||
override val player: ServerPlayer,
|
||||
override val pokemon: PokemonEntity,
|
||||
var rideStamina: Float
|
||||
) : RidePokemonEvent {
|
||||
val context = mutableMapOf(
|
||||
"player" to player.asMoLangValue(),
|
||||
"pokemon" to pokemon.struct,
|
||||
"ride_stamina" to DoubleValue(rideStamina)
|
||||
)
|
||||
val functions = moLangFunctionMap(
|
||||
"set_ride_stamina" to { params ->
|
||||
rideStamina = params.getDouble(0).toFloat().coerceIn(0F, 1F)
|
||||
DoubleValue.ONE
|
||||
},
|
||||
"set_infinite_stamina" to { _ ->
|
||||
rideStamina = -1F
|
||||
DoubleValue.ONE
|
||||
},
|
||||
)
|
||||
|
||||
fun setInfiniteStamina() {
|
||||
rideStamina = -1F
|
||||
}
|
||||
|
||||
fun isInfiniteStamina() = rideStamina == -1F
|
||||
}
|
||||
}
|
||||
+1
-2
@@ -15,7 +15,6 @@ import net.minecraft.world.entity.LivingEntity
|
||||
import org.joml.Matrix3f
|
||||
import org.joml.Quaternionf
|
||||
import org.joml.Vector3f
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.asin
|
||||
import kotlin.math.sign
|
||||
|
||||
@@ -114,7 +113,7 @@ open class OrientationController(val entity: LivingEntity) {
|
||||
|
||||
fun applyGlobalPitch(deltaPitchDegrees: Float) = updateOrientation { original ->
|
||||
val currQuat = Quaternionf().setFromUnnormalized(original)
|
||||
val horzLeftVector = Vector3f(0.0f, -abs(this.upVector.y.sign), 0.0f).cross(this.forwardVector)
|
||||
val horzLeftVector = Vector3f(0.0f, this.upVector.y.sign, 0.0f).cross(this.forwardVector)
|
||||
// Avoid NaN issue when normalizing and the forwardVector and upVector are equal
|
||||
val pitchAxis = if (horzLeftVector.lengthSquared() < 0.01) this.leftVector else horzLeftVector
|
||||
|
||||
|
||||
@@ -131,7 +131,6 @@ open class PokemonProperties {
|
||||
props.species = parseSpeciesIdentifier(keyPairs)
|
||||
props.form = parseForm(keyPairs)
|
||||
props.friendship = parseIntProperty(keyPairs, listOf("friendship"))?.coerceIn(0, Cobblemon.config.maxPokemonFriendship)
|
||||
props.fullness = parseIntProperty(keyPairs, listOf("fullness"))
|
||||
props.pokeball = parseIdentifierOfRegistry(keyPairs, listOf("pokeball")) { identifier -> PokeBalls.getPokeBall(identifier)?.name?.toString() }
|
||||
props.nature = parseIdentifierOfRegistry(keyPairs, listOf("nature")) { identifier -> Natures.getNature(identifier)?.name?.toString() }
|
||||
props.ability = parseStringOfRegistry(keyPairs, listOf("ability")) { Abilities.get(it)?.name }
|
||||
@@ -327,7 +326,6 @@ open class PokemonProperties {
|
||||
var gender: Gender? = null
|
||||
var level: Int? = null
|
||||
var friendship: Int? = null
|
||||
var fullness: Int? = null
|
||||
var pokeball: String? = null
|
||||
var nature: String? = null
|
||||
var ability: String? = null
|
||||
@@ -399,7 +397,6 @@ open class PokemonProperties {
|
||||
pokemon.setFriendship(pokemon.form.baseFriendship)
|
||||
}
|
||||
}
|
||||
fullness?.let { pokemon.currentFullness = it }
|
||||
pokeball?.let { PokeBalls.getPokeBall(it.asIdentifierDefaultingNamespace())?.let { pokeball -> pokemon.caughtBall = pokeball } }
|
||||
nature?.let { Natures.getNature(it.asIdentifierDefaultingNamespace())?.let { nature -> pokemon.nature = nature } }
|
||||
customProperties.forEach { it.apply(pokemon) }
|
||||
@@ -507,7 +504,6 @@ open class PokemonProperties {
|
||||
nickname?.takeIf { it.string != pokemon.nickname?.string }?.let { return false }
|
||||
form?.takeIf { !it.equals(pokemon.form.name, true) }?.let { return false }
|
||||
friendship?.takeIf { it != pokemon.friendship }?.let { return false }
|
||||
fullness?.takeIf { it != pokemon.currentFullness }?.let { return false }
|
||||
pokeball?.takeIf { it != pokemon.caughtBall.name.toString() }?.let { return false }
|
||||
nature?.takeIf { it != pokemon.nature.name.toString() }?.let { return false }
|
||||
ability?.takeIf { it != pokemon.ability.name }?.let { return false }
|
||||
@@ -592,7 +588,6 @@ open class PokemonProperties {
|
||||
originalTrainer?.takeIf { it != properties.originalTrainer }?.let{ return false }
|
||||
originalTrainerType?.takeIf { it != properties.originalTrainerType }?.let{ return false }
|
||||
moves?.takeIf { it.any { move -> properties.moves?.none { it == move } == true } }?.let { return false }
|
||||
fullness?.takeIf { it != properties.fullness }?.let { return false }
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -641,7 +636,6 @@ open class PokemonProperties {
|
||||
nickname?.let { nbt.putString(DataKeys.POKEMON_NICKNAME, Component.Serializer.toJson(it, registryLookup)) }
|
||||
form?.let { nbt.putString(DataKeys.POKEMON_FORM_ID, it) }
|
||||
friendship?.let { nbt.putInt(DataKeys.POKEMON_FRIENDSHIP, it) }
|
||||
fullness?.let { nbt.putInt(DataKeys.POKEMON_FULLNESS, it) }
|
||||
pokeball?.let { nbt.putString(DataKeys.POKEMON_CAUGHT_BALL, it) }
|
||||
nature?.let { nbt.putString(DataKeys.POKEMON_NATURE, it) }
|
||||
ability?.let { nbt.putString(DataKeys.POKEMON_ABILITY, it) }
|
||||
@@ -673,7 +667,6 @@ open class PokemonProperties {
|
||||
nickname = if (tag.contains(DataKeys.POKEMON_NICKNAME)) Component.Serializer.fromJson(tag.getString(DataKeys.POKEMON_NICKNAME), registryLookup) else null
|
||||
form = if (tag.contains(DataKeys.POKEMON_FORM_ID)) tag.getString(DataKeys.POKEMON_FORM_ID) else null
|
||||
friendship = if (tag.contains(DataKeys.POKEMON_FRIENDSHIP)) tag.getInt(DataKeys.POKEMON_FRIENDSHIP) else null
|
||||
fullness = if (tag.contains(DataKeys.POKEMON_FULLNESS)) tag.getInt(DataKeys.POKEMON_FULLNESS) else null
|
||||
pokeball = if (tag.contains(DataKeys.POKEMON_CAUGHT_BALL)) tag.getString(DataKeys.POKEMON_CAUGHT_BALL) else null
|
||||
nature = if (tag.contains(DataKeys.POKEMON_NATURE)) tag.getString(DataKeys.POKEMON_NATURE) else null
|
||||
ability = if (tag.contains(DataKeys.POKEMON_ABILITY)) tag.getString(DataKeys.POKEMON_ABILITY) else null
|
||||
@@ -707,7 +700,6 @@ open class PokemonProperties {
|
||||
//nickname?.let { json.addProperty(DataKeys.POKEMON_NICKNAME, Text.Serialization.toJsonString(it)) }
|
||||
form?.let { json.addProperty(DataKeys.POKEMON_FORM_ID, it) }
|
||||
friendship?.let { json.addProperty(DataKeys.POKEMON_FRIENDSHIP, it) }
|
||||
fullness?.let {json.addProperty(DataKeys.POKEMON_FULLNESS, it)}
|
||||
pokeball?.let { json.addProperty(DataKeys.POKEMON_CAUGHT_BALL, it) }
|
||||
nature?.let { json.addProperty(DataKeys.POKEMON_NATURE, it) }
|
||||
ability?.let { json.addProperty(DataKeys.POKEMON_ABILITY, it) }
|
||||
@@ -740,7 +732,6 @@ open class PokemonProperties {
|
||||
//nickname = json.get(DataKeys.POKEMON_NICKNAME)?.asString?.let { Text.Serialization.fromJson(it) }
|
||||
form = json.get(DataKeys.POKEMON_FORM_ID)?.asString
|
||||
friendship = json.get(DataKeys.POKEMON_FRIENDSHIP)?.asInt
|
||||
fullness = json.get(DataKeys.POKEMON_FULLNESS)?.asInt
|
||||
pokeball = json.get(DataKeys.POKEMON_CAUGHT_BALL)?.asString
|
||||
nature = json.get(DataKeys.POKEMON_NATURE)?.asString
|
||||
ability = json.get(DataKeys.POKEMON_ABILITY)?.asString
|
||||
@@ -772,7 +763,6 @@ open class PokemonProperties {
|
||||
shiny?.let { pieces.add("shiny=$it") }
|
||||
gender?.let { pieces.add("gender=$it")}
|
||||
friendship?.let { pieces.add("friendship=$it") }
|
||||
fullness?.let {pieces.add("fullness=$it")}
|
||||
pokeball?.let { pieces.add("pokeball=$it") }
|
||||
nature?.let { pieces.add("nature=$it") }
|
||||
ability?.let { pieces.add("ability=$it") }
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.riding
|
||||
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviour
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviourSettings
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviourState
|
||||
import net.minecraft.world.entity.PlayerRideableJumping
|
||||
|
||||
/**
|
||||
|
||||
@@ -9,7 +9,10 @@
|
||||
package com.cobblemon.mod.common.api.riding
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviourSettings
|
||||
import com.cobblemon.mod.common.api.riding.stats.RidingStat
|
||||
import com.cobblemon.mod.common.api.riding.stats.RidingStatDefinition
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import com.cobblemon.mod.common.util.adapters.RidingBehaviourSettingsAdapter
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
@@ -29,10 +32,10 @@ class RidingProperties(
|
||||
{ buffer.readEnumConstant(RidingStyle::class.java) },
|
||||
{
|
||||
val key = buffer.readResourceLocation()
|
||||
val behaviour = RidingBehaviourSettingsAdapter.types[key]?.getConstructor()?.newInstance()
|
||||
val settings = RidingBehaviourSettingsAdapter.types[key]?.getConstructor()?.newInstance()
|
||||
?: error("Unknown controller key: $key")
|
||||
behaviour.decode(buffer)
|
||||
behaviour
|
||||
settings.decode(buffer)
|
||||
settings
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -48,10 +51,7 @@ class RidingProperties(
|
||||
buffer.writeMap(
|
||||
v,
|
||||
{ _, style -> buffer.writeEnumConstant(style) },
|
||||
{ _, behaviour ->
|
||||
buffer.writeResourceLocation(behaviour.key)
|
||||
behaviour.encode(buffer)
|
||||
}
|
||||
{ _, behaviour -> behaviour.encode(buffer) }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+4
-5
@@ -19,17 +19,16 @@ import net.minecraft.resources.ResourceLocation
|
||||
* Typically this will be initialized for each pokemon form during deserialization
|
||||
* to determine how they should ride.
|
||||
*
|
||||
* These also exist in a datapacked folder, ride_settings, which are used for the fallback
|
||||
* values if non-stat settings are omitted in the pokemon form JSON.
|
||||
*
|
||||
* @author landonjw
|
||||
*/
|
||||
interface RidingBehaviourSettings: Encodable, Decodable {
|
||||
val key: ResourceLocation
|
||||
val stats: MutableMap<RidingStat, IntRange>
|
||||
|
||||
fun calculate(stat: RidingStat, boostAmount: Float): Float {
|
||||
fun calculate(stat: RidingStat, boostedAmount: Float): Float {
|
||||
val range = stats[stat] ?: return 0F
|
||||
return range.first + boostAmount
|
||||
return (range.first + boostedAmount).coerceAtMost(range.last.toFloat())
|
||||
}
|
||||
|
||||
fun hasStat(stat: RidingStat) = stats.containsKey(stat)
|
||||
}
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ import net.minecraft.world.phys.Vec3
|
||||
* This is intended to contain mutable state that is passed between the client and server
|
||||
* or temporary state that is used during the riding process.
|
||||
*
|
||||
* This will be destroyed when the main rider dismounts the Pokemon.
|
||||
* This will be destroyed when the a user dismounts the Pokemon.
|
||||
*
|
||||
* @author landonjw
|
||||
*/
|
||||
|
||||
-12
@@ -8,17 +8,13 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.riding.behaviour
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.DoubleJump
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle
|
||||
import com.cobblemon.mod.common.client.MountedCameraTypeHandler
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.tags.FluidTags
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import kotlin.collections.get
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.entity.player.Player
|
||||
|
||||
/**
|
||||
* Small wrapper around a RidingBehaviour to provide sane defaults in the event that the behaviour is not active.
|
||||
@@ -54,14 +50,6 @@ class RidingController(
|
||||
val newState = RidingBehaviours.get(behaviourSettings.key).createDefaultState(behaviourSettings)
|
||||
context?.let { newState.stamina.set(it.state.stamina.get(), forced = true) }
|
||||
context?.let { newState.rideVelocity.set(it.state.rideVelocity.get(), forced = true) }
|
||||
val previousKey = context?.behaviour
|
||||
val newKey = behaviourSettings.key
|
||||
for (passenger in entity.passengers) {
|
||||
if (passenger is Player && passenger !is ServerPlayer) {
|
||||
MountedCameraTypeHandler.handleTransition(previousKey ?: continue, newKey)
|
||||
}
|
||||
}
|
||||
|
||||
context = ActiveRidingContext(behaviourSettings.key, behaviourSettings, newState, newTransition)
|
||||
lastTransitionAge = entity.ticksLived
|
||||
} else {
|
||||
|
||||
+65
-107
@@ -11,7 +11,6 @@ package com.cobblemon.mod.common.api.riding.behaviour.types.air
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.bedrockk.molang.runtime.MoLangMath.lerp
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonRideSettings
|
||||
import com.cobblemon.mod.common.OrientationControllable
|
||||
import com.cobblemon.mod.common.api.orientation.OrientationController
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle
|
||||
@@ -27,13 +26,11 @@ import com.cobblemon.mod.common.util.math.geometry.toRadians
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.Mth
|
||||
import net.minecraft.util.SmoothDouble
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.Vec2
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
import kotlin.math.*
|
||||
|
||||
class BirdBehaviour : RidingBehaviour<BirdSettings, BirdState> {
|
||||
@@ -50,22 +47,8 @@ class BirdBehaviour : RidingBehaviour<BirdSettings, BirdState> {
|
||||
val poseProvider = PoseProvider<BirdSettings, BirdState>(PoseType.HOVER)
|
||||
.with(PoseOption(PoseType.FLY) { _, state, _ -> state.rideVelocity.get().z > 0.2 })
|
||||
|
||||
val globalBird: BirdSettings
|
||||
get() = CobblemonRideSettings.bird
|
||||
|
||||
override fun isActive(settings: BirdSettings, state: BirdState, vehicle: PokemonEntity): Boolean {
|
||||
return Shapes.create(vehicle.boundingBox).blockPositionsAsListRounded().any {
|
||||
//Need to check other fluids
|
||||
if (vehicle.isInWater || vehicle.isUnderWater) {
|
||||
return@any false
|
||||
}
|
||||
//This might not actually work, depending on what the yPos actually is. yPos of the middle of the entity? the feet?
|
||||
if (it.y.toDouble() == (vehicle.position().y)) {
|
||||
val blockState = vehicle.level().getBlockState(it.below())
|
||||
return@any !(!blockState.isAir && blockState.fluidState.isEmpty)
|
||||
}
|
||||
true
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun pose(settings: BirdSettings, state: BirdState, vehicle: PokemonEntity): PoseType {
|
||||
@@ -99,11 +82,12 @@ class BirdBehaviour : RidingBehaviour<BirdSettings, BirdState> {
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player,
|
||||
) {
|
||||
// Also checks stamina
|
||||
val controller = (driver as OrientationControllable).orientationController
|
||||
if (cos(controller.roll.toRadians()) < 0.0) {
|
||||
val upsideDownRate = 1.0 / (2.0 * 20.0) // 2 seconds to max out upsideDown force
|
||||
state.currUpsideDownForce.set( min(1.0, state.currUpsideDownForce.get() + upsideDownRate * abs(cos(controller.roll.toRadians()))))
|
||||
} else if (state.stamina.get() == 0.0f) { // checks stamina depletion and forces dive if depleted
|
||||
} else if (state.stamina.get() == 0.0f) {
|
||||
val upsideDownRate = 1.0 / (2.0 * 20.0) // 1 seconds to max out
|
||||
state.currUpsideDownForce.set( min(1.0, state.currUpsideDownForce.get() + upsideDownRate))
|
||||
} else { // Its right side up or has stamina so reset it
|
||||
@@ -122,12 +106,12 @@ class BirdBehaviour : RidingBehaviour<BirdSettings, BirdState> {
|
||||
// Grab the boost time in seconds and convert to ticks. Then calculate the drain rate as inversely
|
||||
// proportional to the number of ticks of boost thus making a full boost take x ticks
|
||||
// in short: "Stamina drains slower at higher values and also replenishes slower"
|
||||
val totalStam = vehicle.runtime.resolveDouble(settings.staminaExpr ?: globalBird.staminaExpr!!) * 20.0f
|
||||
val totalStam = vehicle.runtime.resolveDouble(settings.staminaExpr) * 20.0f
|
||||
val stamDrainRate = (1.0f / totalStam).toFloat()
|
||||
|
||||
val newStam = if (driver.zza > 0.0) max(0.0f,stam - stamDrainRate)
|
||||
else if (!state.gliding.get()) max(0.0f,stam - stamDrainRate * 0.5f) // if hovering half the stam drain
|
||||
else min(1.0f,stam + stamDrainRate * 0.2f)
|
||||
else stam
|
||||
|
||||
state.stamina.set(newStam)
|
||||
}
|
||||
@@ -178,9 +162,9 @@ class BirdBehaviour : RidingBehaviour<BirdSettings, BirdState> {
|
||||
*/
|
||||
fun calculateRideSpaceVel(settings: BirdSettings, state: BirdState, vehicle: PokemonEntity, driver: Player) {
|
||||
// retrieve stats
|
||||
val topSpeed = (vehicle.runtime.resolveDouble(settings.speedExpr ?: globalBird.speedExpr!!) / 20.0)
|
||||
val accel = topSpeed / (vehicle.runtime.resolveDouble(settings.accelerationExpr ?: globalBird.accelerationExpr!!) * 20.0)
|
||||
val glideTopSpeed = topSpeed * vehicle.runtime.resolveDouble(settings.glideSpeedExpr ?: globalBird.glideSpeedExpr!!)
|
||||
val topSpeed = (vehicle.runtime.resolveDouble(settings.speedExpr) / 20.0)
|
||||
val accel = topSpeed / (vehicle.runtime.resolveDouble(settings.accelerationExpr) * 20.0)
|
||||
val glideTopSpeed = topSpeed * vehicle.runtime.resolveDouble(settings.glidespeedExpr)
|
||||
var glideSpeedChange = 0.0
|
||||
var activeInput = false
|
||||
|
||||
@@ -289,23 +273,21 @@ class BirdBehaviour : RidingBehaviour<BirdSettings, BirdState> {
|
||||
if (driver !is OrientationControllable) return Vec3.ZERO
|
||||
val controller = (driver as OrientationControllable).orientationController
|
||||
|
||||
val handling = vehicle.runtime.resolveDouble(settings.handlingExpr ?: globalBird.handlingExpr!!)
|
||||
val topSpeed = vehicle.runtime.resolveDouble(settings.speedExpr ?: globalBird.speedExpr!!) / 20.0
|
||||
val handling = vehicle.runtime.resolveDouble(settings.handlingExpr)
|
||||
val topSpeed = vehicle.runtime.resolveDouble(settings.speedExpr) / 20.0
|
||||
|
||||
val yawDeltaDeg = deltaTime * handling * sin(Math.toRadians(controller.roll.toDouble())) //* sin(Math.toRadians(controller.roll.toDouble())).sign
|
||||
val trueYawDelt = yawDeltaDeg * abs(cos(Math.toRadians(controller.pitch.toDouble())))// * sqrt(RidingBehaviour.scaleToRange(state.rideVelocity.get().length(), 0.0, topSpeed))
|
||||
val yawDeltaDeg = deltaTime * handling * sin(Math.toRadians(controller.roll.toDouble())).pow(2) * sin(Math.toRadians(controller.roll.toDouble())).sign
|
||||
val trueYawDelt = yawDeltaDeg * abs(cos(Math.toRadians(controller.pitch.toDouble()))) * sqrt(RidingBehaviour.scaleToRange(state.rideVelocity.get().length(), 0.0, topSpeed))
|
||||
|
||||
// Dampen yaw when upside down
|
||||
val yawDampen = (1 - abs(min(cos(controller.roll.toRadians()),0.0f)).pow(2))
|
||||
val yawDampen = (1 - abs(min(cos(controller.roll.toRadians()),0.0f)))
|
||||
controller.applyGlobalYaw(trueYawDelt.toFloat() * yawDampen)
|
||||
|
||||
// Correct orientation when at low speeds
|
||||
correctOrientation(settings, state, vehicle, controller, deltaTime)
|
||||
|
||||
controller.applyGlobalPitch(state.currPitchCorrectionForce.get().toRadians())
|
||||
|
||||
//yaw, pitch, roll
|
||||
return Vec3(0.0, 0.0, state.currRollCorrectionForce.get())
|
||||
return Vec3(0.0, state.currPitchCorrectionForce.get(), state.currRollCorrectionForce.get())
|
||||
}
|
||||
|
||||
private fun correctOrientation(
|
||||
@@ -317,8 +299,8 @@ class BirdBehaviour : RidingBehaviour<BirdSettings, BirdState> {
|
||||
) {
|
||||
// Calculate correcting roll force.
|
||||
// Mult by cos(pitch) to ensure that it doesn't roll correct at when diving or climbing
|
||||
val rollCorrectionTimer = vehicle.runtime.resolveDouble(settings.timeToRollCorrect ?: globalBird.timeToRollCorrect!!)
|
||||
val maxRollCorrectionRate = if (state.rideVelocity.get().length() < 0.1) 15.0f else 8.0f * (cos(controller.pitch.toRadians())).pow(2) * ((state.noInputTimeRoll.get() - rollCorrectionTimer)).coerceIn(0.0, 1.0).toFloat()
|
||||
val rollCorrectionTimer = vehicle.runtime.resolveDouble(settings.timeToRollCorrect)
|
||||
val maxRollCorrectionRate = if (state.rideVelocity.get().length() < 0.1) 15.0f else 8.0f * (cos(controller.pitch.toRadians())).pow(2) * ((state.noInputTimeRoll.get() - rollCorrectionTimer) * 2).coerceIn(0.0, 1.0).toFloat()
|
||||
val maxRollForce = maxRollCorrectionRate / 40.0
|
||||
val rollArrivalDeg = 90.0
|
||||
if(state.rideVelocity.get().length() < 0.1 || state.noInputTimeRoll.get() > rollCorrectionTimer) {
|
||||
@@ -345,16 +327,12 @@ class BirdBehaviour : RidingBehaviour<BirdSettings, BirdState> {
|
||||
//Calculate correcting pitch force.
|
||||
val maxPitchCorrectionRate = if (state.currUpsideDownForce.get() != 0.0) 8f * state.currUpsideDownForce.get() else 15f
|
||||
val maxPitchForce = maxPitchCorrectionRate.toFloat() / 40.0f
|
||||
val pitchArrivalDeg = 45.0f
|
||||
var desiredPitch = if (state.currUpsideDownForce.get() != 0.0) 90.0 else 0.0
|
||||
// if (cos(controller.roll.toRadians()) < 0.0) {
|
||||
// desiredPitch *= -1 // If not rolled over then flip the pitch force. There are better ways to do this :(
|
||||
// }
|
||||
|
||||
val pitchArrivalDeg = 90.0f
|
||||
val desiredPitch = if (state.currUpsideDownForce.get() != 0.0) 90.0 else 0.0
|
||||
if((state.rideVelocity.get().length() < 0.1 && controller.pitch < 0.0) || state.currUpsideDownForce.get() != 0.0) {
|
||||
val arrivalInfluence = (min(pitchArrivalDeg,abs(Mth.wrapDegrees(desiredPitch.toFloat().angleDifference(controller.pitch)))) / pitchArrivalDeg)
|
||||
val desiredPitchForce = maxPitchCorrectionRate.toFloat() * arrivalInfluence
|
||||
var steeredPitchForce = (desiredPitchForce - state.currPitchCorrectionForce.get())
|
||||
val arrivalInfluence = (min(pitchArrivalDeg,abs(controller.pitch - desiredPitch).toFloat()) / pitchArrivalDeg)
|
||||
val desiredPitchForce = (desiredPitch - controller.pitch).sign * maxPitchCorrectionRate.toFloat() * arrivalInfluence
|
||||
var steeredPitchForce = desiredPitchForce - state.currPitchCorrectionForce.get()
|
||||
|
||||
// Ensure the 'steering' correction force doesn't exceed our maxForce
|
||||
if (abs(steeredPitchForce) > maxPitchForce) {
|
||||
@@ -385,16 +363,11 @@ class BirdBehaviour : RidingBehaviour<BirdSettings, BirdState> {
|
||||
sensitivity: Double,
|
||||
deltaTime: Double
|
||||
): Vec3 {
|
||||
if (driver !is OrientationControllable) return Vec3.ZERO
|
||||
val controller = (driver as OrientationControllable).orientationController
|
||||
// Begin the roll correction time counter if not enough mouse input
|
||||
// is detected
|
||||
if (mouseX < 1 && abs(mouseY) < 1) {
|
||||
if (abs(mouseX) < 1 && abs(mouseY) < 1) {
|
||||
state.noInputTimeRoll.set(state.noInputTimeRoll.get() + deltaTime)
|
||||
} else if (cos(controller.roll.toRadians()) < 0.1) {
|
||||
state.noInputTimeRoll.set(state.noInputTimeRoll.get() + deltaTime * 0.5)
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
state.noInputTimeRoll.set(0.0)
|
||||
}
|
||||
|
||||
@@ -450,8 +423,8 @@ class BirdBehaviour : RidingBehaviour<BirdSettings, BirdState> {
|
||||
// Set roll to zero if transitioning to noroll config
|
||||
controller.rotateRoll(controller.roll * -1.0f)
|
||||
|
||||
val handling = vehicle.runtime.resolveDouble(settings.handlingExpr ?: globalBird.handlingExpr!!)
|
||||
val mouseInputMult = vehicle.runtime.resolveDouble(settings.mouseInputMult ?: globalBird.mouseInputMult!!)
|
||||
val handling = vehicle.runtime.resolveDouble(settings.handlingExpr)
|
||||
val mouseInputMult = vehicle.runtime.resolveDouble(settings.mouseInputMult)
|
||||
|
||||
//Smooth out mouse input.
|
||||
val smoothingSpeed = 4.0
|
||||
@@ -495,11 +468,11 @@ class BirdBehaviour : RidingBehaviour<BirdSettings, BirdState> {
|
||||
if (driver !is OrientationControllable) return Vec3.ZERO
|
||||
val controller = (driver as OrientationControllable).orientationController
|
||||
|
||||
val topSpeed = vehicle.runtime.resolveDouble(settings.speedExpr ?: globalBird.speedExpr!!) / 20.0
|
||||
val mouseInputMult = vehicle.runtime.resolveDouble(settings.mouseInputMult ?: globalBird.mouseInputMult!!)
|
||||
val topSpeed = vehicle.runtime.resolveDouble(settings.speedExpr) / 20.0
|
||||
val mouseInputMult = vehicle.runtime.resolveDouble(settings.mouseInputMult)
|
||||
|
||||
//Smooth out mouse input.
|
||||
val smoothingSpeed = 2.0
|
||||
val smoothingSpeed = 4.0
|
||||
val mouseXc = (mouseX).coerceIn(-45.0, 45.0) * mouseInputMult
|
||||
// When upside down apply a pitching force to nudge the player towards a dive. This reduces the 'weirdness'
|
||||
// of being upside down
|
||||
@@ -511,16 +484,16 @@ class BirdBehaviour : RidingBehaviour<BirdSettings, BirdState> {
|
||||
val currHorzSpeed = state.rideVelocity.get().horizontalDistance()
|
||||
val hoverSpeed = 0.1
|
||||
|
||||
// Yaw locally when at or below hoverSpeed but not when pitched up or rolled over
|
||||
// Yaw locally when at or below hoverSpeed
|
||||
val yawDampen = abs(cos(controller.pitch.toRadians())).pow(2) * abs(cos(controller.roll.toRadians())).pow(2)
|
||||
val localYaw = if (currHorzSpeed < hoverSpeed) xInput * (1 - sqrt(RidingBehaviour.scaleToRange(currHorzSpeed, hoverSpeed, topSpeed))).coerceIn(0.0, 1.0)
|
||||
else 0.0 //xInput * 0.4 * cos(controller.roll.toRadians()).coerceIn(0.0f, 1.0f) * yawDampen
|
||||
else xInput * 0.4 * cos(controller.roll.toRadians()).coerceIn(0.0f, 1.0f) * yawDampen
|
||||
|
||||
// Pitch locally up or down depending upon a number of factors:
|
||||
// - Reduce pitch substantially when rolled and in a steep yaw. This prevents the player from ignoring a slow handling stat
|
||||
// - Do not pitch at all when at or below hover speed
|
||||
// - pitch faster at higher speeds
|
||||
val p = 1.0 - vehicle.runtime.resolveDouble(settings.horizontalPitchExpr ?: globalBird.horizontalPitchExpr!!)
|
||||
val p = 1.0 - vehicle.runtime.resolveDouble(settings.horizontalPitchExpr)
|
||||
var localPitch = yInput * (1 - abs(sin(controller.roll.toRadians())).pow(2) * p * hypot(controller.forwardVector.x.toDouble(), controller.forwardVector.z.toDouble()).toFloat())
|
||||
localPitch *= if (currSpeed > hoverSpeed || yInput > 0.0) RidingBehaviour.scaleToRange(currSpeed, 0.0, topSpeed).coerceIn(0.2, 1.0)
|
||||
else 0.0
|
||||
@@ -529,10 +502,7 @@ class BirdBehaviour : RidingBehaviour<BirdSettings, BirdState> {
|
||||
// Apply a roll righting force when trying to pitch hard while rolled sideways. This nudges the player towards
|
||||
// pitching globally
|
||||
val pitchInfluencedRollCorrection = 0.0
|
||||
val howRolledAmI = (( cos(controller.roll.toRadians()) - 1).coerceIn(-1.0f, 0.0f) * -2).coerceIn(0.0f, 0.7f) //Coerce into how much roll you want to let in in the deadzone
|
||||
val inputInRolledDir = if (xInput.sign.toFloat() == controller.roll.sign) 1.0 else -cos(controller.roll.toRadians()).coerceIn(-1.0f, 0.0f).toDouble()
|
||||
val rollDampen = (1 - howRolledAmI * abs(cos(controller.pitch.toRadians())).pow(2) * inputInRolledDir)
|
||||
val rollForce = if (currHorzSpeed > hoverSpeed) xInput * sqrt(abs(RidingBehaviour.scaleToRange(currHorzSpeed, hoverSpeed, topSpeed)).coerceIn(0.0,1.0)) * rollDampen + pitchInfluencedRollCorrection
|
||||
val rollForce = if (currHorzSpeed > hoverSpeed) xInput * sqrt(abs(RidingBehaviour.scaleToRange(currHorzSpeed, hoverSpeed, topSpeed)).coerceIn(0.0,1.0)) + pitchInfluencedRollCorrection
|
||||
else 0.0
|
||||
|
||||
//yaw, pitch, roll
|
||||
@@ -583,8 +553,8 @@ class BirdBehaviour : RidingBehaviour<BirdSettings, BirdState> {
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): Float {
|
||||
val topSpeed = vehicle.runtime.resolveDouble(settings.speedExpr ?: globalBird.speedExpr!!) / 20.0
|
||||
val glideTopSpeed = topSpeed * vehicle.runtime.resolveDouble(settings.glideSpeedExpr ?: globalBird.glideSpeedExpr!!)
|
||||
val topSpeed = vehicle.runtime.resolveDouble(settings.speedExpr) / 20.0
|
||||
val glideTopSpeed = topSpeed * vehicle.runtime.resolveDouble(settings.glidespeedExpr)
|
||||
val currSpeed = state.rideVelocity.get().length()
|
||||
|
||||
// Must I ensure that topspeed is greater than minimum?
|
||||
@@ -672,56 +642,57 @@ class BirdSettings : RidingBehaviourSettings {
|
||||
override val key = BirdBehaviour.KEY
|
||||
override val stats = mutableMapOf<RidingStat, IntRange>()
|
||||
|
||||
var infiniteAltitude: Expression? = null
|
||||
var infiniteAltitude: Expression = "false".asExpression()
|
||||
private set
|
||||
|
||||
var infiniteStamina: Expression? = null
|
||||
var infiniteStamina: Expression = "false".asExpression()
|
||||
private set
|
||||
|
||||
var timeToRollCorrect: Expression? = null
|
||||
var timeToRollCorrect: Expression = "0.5".asExpression()
|
||||
private set
|
||||
|
||||
var handlingExpr: Expression? = null
|
||||
var horizontalPitchExpr: Expression? = null
|
||||
var mouseInputMult: Expression? = null
|
||||
var speedExpr: Expression? = null
|
||||
var handlingExpr: Expression = "q.get_ride_stats('SKILL', 'AIR', 45.0, 10.0)".asExpression()
|
||||
var horizontalPitchExpr: Expression = "q.get_ride_stats('SKILL', 'AIR', 0.2, 0.1)".asExpression()
|
||||
var mouseInputMult: Expression = "q.get_ride_stats('SKILL', 'AIR', 1.2, 0.8)".asExpression()
|
||||
var speedExpr: Expression = "q.get_ride_stats('SPEED', 'AIR', 20.0, 4.0)".asExpression()
|
||||
// Seconds from stationary to top speed
|
||||
var accelerationExpr: Expression? = null
|
||||
var staminaExpr: Expression? = null
|
||||
var accelerationExpr: Expression = "q.get_ride_stats('ACCELERATION', 'AIR', 2.0, 8.0)".asExpression()
|
||||
var staminaExpr: Expression = "q.get_ride_stats('STAMINA', 'AIR', 60.0, 15.0)".asExpression()
|
||||
|
||||
var glideSpeedExpr: Expression? = null
|
||||
var glidespeedExpr: Expression = "q.get_ride_stats('JUMP', 'AIR', 2.0, 1.0)".asExpression()
|
||||
private set
|
||||
|
||||
var rideSounds: RideSoundSettingsList = RideSoundSettingsList()
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeResourceLocation(key)
|
||||
buffer.writeRidingStats(stats)
|
||||
rideSounds.encode(buffer)
|
||||
buffer.writeNullableExpression(infiniteAltitude)
|
||||
buffer.writeNullableExpression(infiniteStamina)
|
||||
buffer.writeNullableExpression(glideSpeedExpr)
|
||||
buffer.writeNullableExpression(handlingExpr)
|
||||
buffer.writeNullableExpression(horizontalPitchExpr)
|
||||
buffer.writeNullableExpression(mouseInputMult)
|
||||
buffer.writeNullableExpression(speedExpr)
|
||||
buffer.writeNullableExpression(accelerationExpr)
|
||||
buffer.writeNullableExpression(staminaExpr)
|
||||
buffer.writeNullableExpression(timeToRollCorrect)
|
||||
buffer.writeExpression(infiniteAltitude)
|
||||
buffer.writeExpression(infiniteStamina)
|
||||
buffer.writeExpression(glidespeedExpr)
|
||||
buffer.writeExpression(handlingExpr)
|
||||
buffer.writeExpression(horizontalPitchExpr)
|
||||
buffer.writeExpression(mouseInputMult)
|
||||
buffer.writeExpression(speedExpr)
|
||||
buffer.writeExpression(accelerationExpr)
|
||||
buffer.writeExpression(staminaExpr)
|
||||
buffer.writeExpression(timeToRollCorrect)
|
||||
}
|
||||
|
||||
override fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
stats.putAll(buffer.readRidingStats())
|
||||
rideSounds = RideSoundSettingsList.decode(buffer)
|
||||
infiniteAltitude = buffer.readNullableExpression()
|
||||
infiniteStamina = buffer.readNullableExpression()
|
||||
glideSpeedExpr = buffer.readNullableExpression()
|
||||
handlingExpr = buffer.readNullableExpression()
|
||||
horizontalPitchExpr = buffer.readNullableExpression()
|
||||
mouseInputMult = buffer.readNullableExpression()
|
||||
speedExpr = buffer.readNullableExpression()
|
||||
accelerationExpr = buffer.readNullableExpression()
|
||||
staminaExpr = buffer.readNullableExpression()
|
||||
timeToRollCorrect = buffer.readNullableExpression()
|
||||
infiniteAltitude = buffer.readExpression()
|
||||
infiniteStamina = buffer.readExpression()
|
||||
glidespeedExpr = buffer.readExpression()
|
||||
handlingExpr = buffer.readExpression()
|
||||
horizontalPitchExpr = buffer.readExpression()
|
||||
mouseInputMult = buffer.readExpression()
|
||||
speedExpr = buffer.readExpression()
|
||||
accelerationExpr = buffer.readExpression()
|
||||
staminaExpr = buffer.readExpression()
|
||||
timeToRollCorrect = buffer.readExpression()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -775,16 +746,3 @@ class BirdState : RidingBehaviourState() {
|
||||
return super.shouldSync(previous)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the shortest difference between two angles.
|
||||
* The result will be in the range [-180, 180].
|
||||
* A positive result indicates a clockwise direction from this angle to the other,
|
||||
* a negative result indicates a counter-clockwise direction.
|
||||
*/
|
||||
fun Float.angleDifference(other: Float): Float {
|
||||
var diff = other - this
|
||||
while (diff <= -180F) diff += 360F
|
||||
while (diff > 180F) diff -= 360F
|
||||
return diff
|
||||
}
|
||||
|
||||
+14
-16
@@ -10,7 +10,6 @@ package com.cobblemon.mod.common.api.riding.behaviour.types.air
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonRideSettings
|
||||
import com.cobblemon.mod.common.OrientationControllable
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviourState
|
||||
@@ -38,9 +37,6 @@ class GliderBehaviour : RidingBehaviour<GliderSettings, RidingBehaviourState> {
|
||||
|
||||
override val key = KEY
|
||||
|
||||
val globalGlider: GliderSettings
|
||||
get() = CobblemonRideSettings.glider
|
||||
|
||||
override fun getRidingStyle(settings: GliderSettings, state: RidingBehaviourState): RidingStyle {
|
||||
return RidingStyle.AIR
|
||||
}
|
||||
@@ -57,7 +53,7 @@ class GliderBehaviour : RidingBehaviour<GliderSettings, RidingBehaviourState> {
|
||||
}
|
||||
|
||||
override fun speed(settings: GliderSettings, state: RidingBehaviourState, vehicle: PokemonEntity, driver: Player): Float {
|
||||
return vehicle.runtime.resolveFloat(settings.speed ?: globalGlider.speed!!)
|
||||
return vehicle.runtime.resolveFloat(settings.speed)
|
||||
}
|
||||
|
||||
override fun rotation(
|
||||
@@ -76,9 +72,10 @@ class GliderBehaviour : RidingBehaviour<GliderSettings, RidingBehaviourState> {
|
||||
driver: Player,
|
||||
input: Vec3
|
||||
): Vec3 {
|
||||
val xVector = if (vehicle.runtime.resolveBoolean(settings.canStrafe ?: globalGlider.canStrafe!!)) driver.xxa.toDouble() else 0.0
|
||||
val yVector = -vehicle.runtime.resolveDouble(settings.glideSpeed ?: globalGlider.glideSpeed!!)
|
||||
val xVector = if (vehicle.runtime.resolveBoolean(settings.canStrafe)) driver.xxa.toDouble() else 0.0
|
||||
val yVector = -vehicle.runtime.resolveDouble(settings.glideSpeed)
|
||||
val zVector = driver.zza.toDouble()
|
||||
val speedStat = settings.calculate(RidingStat.SPEED, 0F)
|
||||
return Vec3(xVector, yVector, zVector)
|
||||
}
|
||||
|
||||
@@ -199,30 +196,31 @@ class GliderSettings : RidingBehaviourSettings {
|
||||
override val key = GliderBehaviour.KEY
|
||||
override val stats = mutableMapOf<RidingStat, IntRange>()
|
||||
|
||||
var glideSpeed: Expression? = null
|
||||
var glideSpeed: Expression = "0.1".asExpression()
|
||||
private set
|
||||
|
||||
var speed: Expression? = null
|
||||
var speed: Expression = "1.0".asExpression()
|
||||
private set
|
||||
|
||||
var canStrafe: Expression? = null
|
||||
var canStrafe: Expression = "false".asExpression()
|
||||
private set
|
||||
|
||||
var rideSounds: RideSoundSettingsList = RideSoundSettingsList()
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeResourceLocation(key)
|
||||
buffer.writeRidingStats(stats)
|
||||
rideSounds.encode(buffer)
|
||||
buffer.writeNullableExpression(glideSpeed)
|
||||
buffer.writeNullableExpression(speed)
|
||||
buffer.writeNullableExpression(canStrafe)
|
||||
buffer.writeExpression(glideSpeed)
|
||||
buffer.writeExpression(speed)
|
||||
buffer.writeExpression(canStrafe)
|
||||
}
|
||||
|
||||
override fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
stats.putAll(buffer.readRidingStats())
|
||||
rideSounds = RideSoundSettingsList.decode(buffer)
|
||||
glideSpeed = buffer.readNullableExpression()
|
||||
speed = buffer.readNullableExpression()
|
||||
canStrafe = buffer.readNullableExpression()
|
||||
glideSpeed = buffer.readExpression()
|
||||
speed = buffer.readExpression()
|
||||
canStrafe = buffer.readExpression()
|
||||
}
|
||||
}
|
||||
|
||||
+19
-27
@@ -10,7 +10,6 @@ package com.cobblemon.mod.common.api.riding.behaviour.types.air
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonRideSettings
|
||||
import com.cobblemon.mod.common.OrientationControllable
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviour
|
||||
@@ -22,16 +21,7 @@ import com.cobblemon.mod.common.api.riding.sound.RideSoundSettingsList
|
||||
import com.cobblemon.mod.common.api.riding.stats.RidingStat
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.blockPositionsAsListRounded
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.readNullableExpression
|
||||
import com.cobblemon.mod.common.util.readRidingStats
|
||||
import com.cobblemon.mod.common.util.resolveDouble
|
||||
import com.cobblemon.mod.common.util.writeNullableExpression
|
||||
import com.cobblemon.mod.common.util.writeRidingStats
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.sin
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.SmoothDouble
|
||||
@@ -40,6 +30,9 @@ import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.Vec2
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.sin
|
||||
|
||||
class HelicopterBehaviour : RidingBehaviour<HelicopterSettings, RidingBehaviourState> {
|
||||
companion object {
|
||||
@@ -48,8 +41,6 @@ class HelicopterBehaviour : RidingBehaviour<HelicopterSettings, RidingBehaviourS
|
||||
}
|
||||
|
||||
override val key = KEY
|
||||
val globalHelicopter: HelicopterSettings
|
||||
get() = CobblemonRideSettings.helicopter
|
||||
|
||||
override fun getRidingStyle(settings: HelicopterSettings, state: RidingBehaviourState): RidingStyle {
|
||||
return RidingStyle.AIR
|
||||
@@ -102,8 +93,8 @@ class HelicopterBehaviour : RidingBehaviour<HelicopterSettings, RidingBehaviourS
|
||||
val runtime = vehicle.runtime
|
||||
|
||||
//If the player is not modulating height then hover
|
||||
var yVel = if (driver.jumping) runtime.resolveDouble(settings.verticalVelocity ?: globalHelicopter.verticalVelocity!!)
|
||||
else if (driver.isShiftKeyDown) -runtime.resolveDouble(settings.verticalVelocity ?: globalHelicopter.verticalVelocity!!)
|
||||
var yVel = if (driver.jumping) runtime.resolveDouble(settings.verticalVelocity)
|
||||
else if (driver.isShiftKeyDown) -runtime.resolveDouble(settings.verticalVelocity)
|
||||
else (0.0)
|
||||
|
||||
yVel *= 0.25
|
||||
@@ -299,35 +290,36 @@ class HelicopterSettings : RidingBehaviourSettings {
|
||||
override val key = HelicopterBehaviour.KEY
|
||||
override val stats = mutableMapOf<RidingStat, IntRange>()
|
||||
|
||||
var gravity: Expression? = null
|
||||
var gravity: Expression = "1.0".asExpression()
|
||||
private set
|
||||
|
||||
var horizontalAcceleration: Expression? = null
|
||||
var horizontalAcceleration: Expression = "0.1".asExpression()
|
||||
private set
|
||||
|
||||
var verticalVelocity: Expression? = null
|
||||
var verticalVelocity: Expression = "1.0".asExpression()
|
||||
private set
|
||||
|
||||
var speed: Expression? = null
|
||||
var speed: Expression = "1.0".asExpression()
|
||||
private set
|
||||
|
||||
var rideSounds: RideSoundSettingsList = RideSoundSettingsList()
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeResourceLocation(key)
|
||||
buffer.writeRidingStats(stats)
|
||||
rideSounds.encode(buffer)
|
||||
buffer.writeNullableExpression(gravity)
|
||||
buffer.writeNullableExpression(horizontalAcceleration)
|
||||
buffer.writeNullableExpression(verticalVelocity)
|
||||
buffer.writeNullableExpression(speed)
|
||||
buffer.writeExpression(gravity)
|
||||
buffer.writeExpression(horizontalAcceleration)
|
||||
buffer.writeExpression(verticalVelocity)
|
||||
buffer.writeExpression(speed)
|
||||
}
|
||||
|
||||
override fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
stats.putAll(buffer.readRidingStats())
|
||||
rideSounds = RideSoundSettingsList.decode(buffer)
|
||||
gravity = buffer.readNullableExpression()
|
||||
horizontalAcceleration = buffer.readNullableExpression()
|
||||
verticalVelocity = buffer.readNullableExpression()
|
||||
speed = buffer.readNullableExpression()
|
||||
gravity = buffer.readExpression()
|
||||
horizontalAcceleration = buffer.readExpression()
|
||||
verticalVelocity = buffer.readExpression()
|
||||
speed = buffer.readExpression()
|
||||
}
|
||||
}
|
||||
|
||||
+26
-39
@@ -9,7 +9,6 @@
|
||||
package com.cobblemon.mod.common.api.riding.behaviour.types.air
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.cobblemon.mod.common.CobblemonRideSettings
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.*
|
||||
import com.cobblemon.mod.common.api.riding.posing.PoseOption
|
||||
@@ -42,8 +41,6 @@ class HoverBehaviour : RidingBehaviour<HoverSettings, HoverState> {
|
||||
}
|
||||
|
||||
override val key = KEY
|
||||
val globalHover: HoverSettings
|
||||
get() = CobblemonRideSettings.hover
|
||||
|
||||
override fun getRidingStyle(settings: HoverSettings, state: HoverState): RidingStyle {
|
||||
return RidingStyle.AIR
|
||||
@@ -108,7 +105,7 @@ class HoverBehaviour : RidingBehaviour<HoverSettings, HoverState> {
|
||||
state: HoverState,
|
||||
vehicle: PokemonEntity,
|
||||
) {
|
||||
val heightLimit = vehicle.runtime.resolveDouble(settings.jumpExpr ?: globalHover.jumpExpr!!)
|
||||
val heightLimit = vehicle.runtime.resolveDouble(settings.jumpExpr)
|
||||
val pos = vehicle.position()
|
||||
val level = Minecraft.getInstance().player?.level() ?: return
|
||||
val hit = level.clip(
|
||||
@@ -129,12 +126,9 @@ class HoverBehaviour : RidingBehaviour<HoverSettings, HoverState> {
|
||||
state: HoverState,
|
||||
vehicle: PokemonEntity
|
||||
) {
|
||||
if (vehicle.runtime.resolveBoolean(settings.infiniteStamina ?: globalHover.infiniteStamina!!)) {
|
||||
return
|
||||
}
|
||||
val stam = state.stamina.get()
|
||||
val stamDrainRate = (1.0f / vehicle.runtime.resolveDouble(settings.staminaExpr ?: globalHover.staminaExpr!!)).toFloat() / 20.0f
|
||||
val stamReplenishRate = (1.0f / vehicle.runtime.resolveDouble(settings.stamReplenishTimeSeconds ?: globalHover.stamReplenishTimeSeconds!!) ).toFloat() / 20.0f // 2 seconds to replenish a full bar of stamina
|
||||
val stamDrainRate = (1.0f / vehicle.runtime.resolveDouble(settings.staminaExpr)).toFloat() / 20.0f
|
||||
val stamReplenishRate = (1.0f / vehicle.runtime.resolveDouble(settings.stamReplenishTimeSeconds) ).toFloat() / 20.0f // 2 seconds to replenish a full bar of stamina
|
||||
val newStam = if (state.tooHigh.get()) max(0.0f, stam - stamDrainRate) else min(1.0f,stam + stamReplenishRate)
|
||||
|
||||
state.stamina.set(newStam)
|
||||
@@ -181,8 +175,8 @@ class HoverBehaviour : RidingBehaviour<HoverSettings, HoverState> {
|
||||
vehicle: PokemonEntity,
|
||||
driver: LivingEntity
|
||||
): Float {
|
||||
val topSpeed = vehicle.runtime.resolveDouble(settings.speedExpr ?: globalHover.speedExpr!!) / 20.0
|
||||
val handling = vehicle.runtime.resolveDouble(settings.handlingExpr ?: globalHover.handlingExpr!!) / 20.0
|
||||
val topSpeed = vehicle.runtime.resolveDouble(settings.speedExpr) / 20.0
|
||||
val handling = vehicle.runtime.resolveDouble(settings.handlingExpr) / 20.0
|
||||
val maxYawDiff = 90.0f
|
||||
|
||||
// Normalize the current rotation diff
|
||||
@@ -217,8 +211,8 @@ class HoverBehaviour : RidingBehaviour<HoverSettings, HoverState> {
|
||||
driver: Player
|
||||
): Vec3 {
|
||||
// Convert these to their tick values
|
||||
val topSpeed = vehicle.runtime.resolveDouble(settings.speedExpr ?: globalHover.speedExpr!!) / 20.0
|
||||
val accel = topSpeed / (vehicle.runtime.resolveDouble(settings.accelerationExpr ?: globalHover.accelerationExpr!!) * 20.0)
|
||||
val topSpeed = vehicle.runtime.resolveDouble(settings.speedExpr) / 20.0
|
||||
val accel = topSpeed / (vehicle.runtime.resolveDouble(settings.accelerationExpr) * 20.0)
|
||||
|
||||
var newVelocity = state.rideVelocity.get()
|
||||
|
||||
@@ -433,61 +427,54 @@ class HoverSettings : RidingBehaviourSettings {
|
||||
override val key = HoverBehaviour.KEY
|
||||
override val stats = mutableMapOf<RidingStat, IntRange>()
|
||||
|
||||
var infiniteStamina: Expression? = null
|
||||
var canJump = "true".asExpression()
|
||||
private set
|
||||
|
||||
var canJump: Expression? = null
|
||||
private set
|
||||
|
||||
var stamReplenishTimeSeconds: Expression? = null
|
||||
var stamReplenishTimeSeconds = "2.0".asExpression()
|
||||
private set
|
||||
|
||||
// Speed in block per second
|
||||
var speedExpr: Expression? = null
|
||||
var speedExpr: Expression = "q.get_ride_stats('SPEED', 'AIR', 7.0, 1.0)".asExpression()
|
||||
private set
|
||||
|
||||
// Acceleration in number of seconds to top speed
|
||||
var accelerationExpr: Expression? = null
|
||||
var accelerationExpr: Expression =
|
||||
"q.get_ride_stats('ACCELERATION', 'AIR', 2.0, 8.0)".asExpression()
|
||||
private set
|
||||
|
||||
// Amount of seconds between boosts
|
||||
var staminaExpr: Expression? = null
|
||||
var staminaExpr: Expression = "q.get_ride_stats('STAMINA', 'AIR', 30.0, 2.0)".asExpression()
|
||||
private set
|
||||
|
||||
// Blocks before stamina drain
|
||||
var jumpExpr: Expression? = null
|
||||
var jumpExpr: Expression = "q.get_ride_stats('JUMP', 'AIR', 16.0, 2.0)".asExpression()
|
||||
private set
|
||||
|
||||
// Turn rate in degrees per second when stationary
|
||||
var handlingExpr: Expression? = null
|
||||
var handlingExpr: Expression = "q.get_ride_stats('SKILL', 'AIR', 270.0, 45.0)".asExpression()
|
||||
private set
|
||||
|
||||
var rideSounds: RideSoundSettingsList = RideSoundSettingsList()
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeResourceLocation(key)
|
||||
buffer.writeRidingStats(stats)
|
||||
rideSounds.encode(buffer)
|
||||
buffer.writeNullableExpression(infiniteStamina)
|
||||
buffer.writeNullableExpression(canJump)
|
||||
buffer.writeNullableExpression(stamReplenishTimeSeconds)
|
||||
buffer.writeNullableExpression(speedExpr)
|
||||
buffer.writeNullableExpression(accelerationExpr)
|
||||
buffer.writeNullableExpression(staminaExpr)
|
||||
buffer.writeNullableExpression(jumpExpr)
|
||||
buffer.writeNullableExpression(handlingExpr)
|
||||
buffer.writeExpression(speedExpr)
|
||||
buffer.writeExpression(accelerationExpr)
|
||||
buffer.writeExpression(staminaExpr)
|
||||
buffer.writeExpression(jumpExpr)
|
||||
buffer.writeExpression(handlingExpr)
|
||||
}
|
||||
|
||||
override fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
stats.putAll(buffer.readRidingStats())
|
||||
rideSounds = RideSoundSettingsList.decode(buffer)
|
||||
infiniteStamina = buffer.readNullableExpression()
|
||||
canJump = buffer.readNullableExpression()
|
||||
stamReplenishTimeSeconds = buffer.readNullableExpression()
|
||||
speedExpr = buffer.readNullableExpression()
|
||||
accelerationExpr = buffer.readNullableExpression()
|
||||
staminaExpr = buffer.readNullableExpression()
|
||||
jumpExpr = buffer.readNullableExpression()
|
||||
handlingExpr = buffer.readNullableExpression()
|
||||
speedExpr = buffer.readExpression()
|
||||
accelerationExpr = buffer.readExpression()
|
||||
staminaExpr = buffer.readExpression()
|
||||
jumpExpr = buffer.readExpression()
|
||||
handlingExpr = buffer.readExpression()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+67
-104
@@ -11,35 +11,22 @@ package com.cobblemon.mod.common.api.riding.behaviour.types.air
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.bedrockk.molang.runtime.MoLangMath.lerp
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonRideSettings
|
||||
import com.cobblemon.mod.common.OrientationControllable
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviour
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviourSettings
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviourState
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.Side
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.ridingState
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.*
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.types.land.HorseSettings
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.types.land.HorseState
|
||||
import com.cobblemon.mod.common.api.riding.posing.PoseOption
|
||||
import com.cobblemon.mod.common.api.riding.posing.PoseProvider
|
||||
import com.cobblemon.mod.common.api.riding.sound.RideSoundSettingsList
|
||||
import com.cobblemon.mod.common.api.riding.stats.RidingStat
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.blockPositionsAsListRounded
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.math.geometry.toRadians
|
||||
import com.cobblemon.mod.common.util.readNullableExpression
|
||||
import com.cobblemon.mod.common.util.readRidingStats
|
||||
import com.cobblemon.mod.common.util.resolveDouble
|
||||
import com.cobblemon.mod.common.util.toVec3d
|
||||
import com.cobblemon.mod.common.util.writeNullableExpression
|
||||
import com.cobblemon.mod.common.util.writeRidingStats
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
import net.minecraft.client.Minecraft
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import com.cobblemon.mod.common.api.riding.sound.RideSoundSettingsList
|
||||
import com.cobblemon.mod.common.api.riding.stats.RidingStat
|
||||
import com.cobblemon.mod.common.config.CobblemonConfig
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.SmoothDouble
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
@@ -47,7 +34,7 @@ import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.Vec2
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
import org.joml.Vector3f
|
||||
import kotlin.math.*
|
||||
|
||||
class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
|
||||
companion object {
|
||||
@@ -60,9 +47,6 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
|
||||
return RidingStyle.AIR
|
||||
}
|
||||
|
||||
val globalJet: JetSettings
|
||||
get() = CobblemonRideSettings.jet
|
||||
|
||||
val poseProvider = PoseProvider<JetSettings, JetState>(PoseType.HOVER)
|
||||
.with(PoseOption(PoseType.FLY) { _, state, _ -> state.rideVelocity.get().z > 0.1 })
|
||||
|
||||
@@ -127,21 +111,15 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
|
||||
) {
|
||||
val stam = state.stamina.get()
|
||||
var newStam = stam
|
||||
val stamDrainRate = (1.0f / vehicle.runtime.resolveDouble(settings.staminaExpr ?: globalJet.staminaExpr!!)).toFloat() / 20.0f
|
||||
val stamDrainRate = (1.0f / vehicle.runtime.resolveDouble(settings.staminaExpr)).toFloat() / 20.0f
|
||||
|
||||
if (state.boosting.get()) {
|
||||
newStam = max(0.0f,stam - stamDrainRate * 1.5f)
|
||||
|
||||
} else {
|
||||
newStam = max(0.0f,stam - stamDrainRate)
|
||||
}
|
||||
|
||||
// If out of stamina then increase noStamTickCnt
|
||||
if (newStam == 0.0f) {
|
||||
state.noStamTickCnt.set(state.noStamTickCnt.get() + 1)
|
||||
} else {
|
||||
state.noStamTickCnt.get()
|
||||
}
|
||||
|
||||
state.stamina.set(newStam)
|
||||
}
|
||||
|
||||
@@ -161,26 +139,27 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
|
||||
driver: Player,
|
||||
input: Vec3
|
||||
): Vec3 {
|
||||
var upForce = 0.0
|
||||
var forwardForce = 0.0
|
||||
|
||||
val controller = (driver as? OrientationControllable)?.orientationController
|
||||
if (controller == null || controller.orientation == null) return Vec3.ZERO
|
||||
|
||||
//Calculate ride space velocity
|
||||
calculateRideSpaceVel(settings, state, vehicle, driver)
|
||||
|
||||
//Translate ride space velocity to world space velocity.
|
||||
if (controller != null) {
|
||||
upForce = if(state.stamina.get() != 0.0f) -1.0 * sin(Math.toRadians(controller.pitch.toDouble())) * state.rideVelocity.get().z
|
||||
else min(0.0, -1.0 * sin(Math.toRadians(controller.pitch.toDouble())) * state.rideVelocity.get().z)
|
||||
forwardForce = cos(Math.toRadians(controller.pitch.toDouble())) * state.rideVelocity.get().z
|
||||
}
|
||||
|
||||
// The downward force used to encourage players to stop flying upside down.
|
||||
val maxDownwardForceTickCnt = 20.0
|
||||
val extraDownwardForce = if(state.stamina.get() == 0.0f) -0.3 * (state.noStamTickCnt.get() / maxDownwardForceTickCnt).coerceIn(0.0, 1.0) else 0.0 // 6 blocks a second downward
|
||||
val extraDownwardForce = if(state.stamina.get() == 0.0f) -0.3 else 0.0 // 6 blocks a second downward
|
||||
|
||||
// Convert the local velocity vector into a world vector
|
||||
val localVelVec = Vector3f(
|
||||
state.rideVelocity.get().x.toFloat(),
|
||||
(state.rideVelocity.get().y).toFloat(),
|
||||
state.rideVelocity.get().z.toFloat() * -1.0f // Flip the z axis to make this left handed? orr.. right handed? idk, flip it though
|
||||
)
|
||||
var worldVelVec = localVelVec.mul(controller.orientation).toVec3d().yRot(vehicle.yRot.toRadians()) // Unrotate preemptively as this vector gets rotate later down the line in MC logic.
|
||||
worldVelVec = worldVelVec.add(0.0, extraDownwardForce, 0.0) // Add the stamina depletion force to bring the ride down.
|
||||
val velocity = Vec3(0.0, upForce + extraDownwardForce, forwardForce)
|
||||
|
||||
return worldVelVec
|
||||
return velocity
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -192,12 +171,12 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
) {
|
||||
val topSpeed = vehicle.runtime.resolveDouble(settings.speedExpr ?: globalJet.speedExpr!!) / 20.0
|
||||
val accel = topSpeed / (vehicle.runtime.resolveDouble(settings.accelerationExpr ?: globalJet.accelerationExpr!!) * 20.0)
|
||||
val deccel = vehicle.runtime.resolveDouble(settings.deccelRate ?: globalJet.deccelRate!!)//0.005
|
||||
val minSpeed = topSpeed * vehicle.runtime.resolveDouble(settings.minSpeedFactor ?: globalJet.minSpeedFactor!!)
|
||||
val speed = state.rideVelocity.get().z
|
||||
val boostMult = vehicle.runtime.resolveDouble(settings.jumpExpr ?: globalJet.jumpExpr!!)
|
||||
val topSpeed = vehicle.runtime.resolveDouble(settings.speedExpr) / 20.0
|
||||
val accel = topSpeed / (vehicle.runtime.resolveDouble(settings.accelerationExpr) * 20.0)
|
||||
val deccel = vehicle.runtime.resolveDouble(settings.deccelRate)//0.005
|
||||
val minSpeed = topSpeed * vehicle.runtime.resolveDouble(settings.minSpeedFactor)
|
||||
val speed = state.rideVelocity.get().length()
|
||||
val boostMult = vehicle.runtime.resolveDouble(settings.jumpExpr)
|
||||
|
||||
val boostTopSpeed = topSpeed * boostMult
|
||||
val boostAccel = accel * boostMult
|
||||
@@ -209,7 +188,7 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
|
||||
Vec3(
|
||||
state.rideVelocity.get().x,
|
||||
state.rideVelocity.get().y,
|
||||
max(state.rideVelocity.get().z - (deccel * 1.3), 0.3 * 0.5)
|
||||
max(state.rideVelocity.get().z - (deccel), minSpeed * 0.5)
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -245,17 +224,6 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
|
||||
state.rideVelocity.get().scale(0.98)
|
||||
)
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Kill strafing velocities carried over from controller transition. Don't
|
||||
* kill immediately to give some momentum to transitions.
|
||||
***************************************************************************/
|
||||
state.rideVelocity.set(Vec3(
|
||||
lerp(state.rideVelocity.get().x, 0.0, 0.03),
|
||||
lerp(state.rideVelocity.get().y, 0.0, 0.03),
|
||||
state.rideVelocity.get().z
|
||||
))
|
||||
|
||||
}
|
||||
|
||||
override fun angRollVel(
|
||||
@@ -272,7 +240,7 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
|
||||
val cappedDeltaTime = min(deltaTime, 0.2)
|
||||
|
||||
//Get handling in degrees per second
|
||||
val yawRotRate = vehicle.runtime.resolveDouble(settings.handlingYawExpr ?: globalJet.handlingYawExpr!!)
|
||||
val yawRotRate = vehicle.runtime.resolveDouble(settings.handlingYawExpr)
|
||||
|
||||
//Base the change off of deltatime.
|
||||
var handlingYaw = yawRotRate * (cappedDeltaTime)
|
||||
@@ -353,7 +321,7 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
|
||||
|
||||
//Get handling in degrees per second
|
||||
val handlingDebuff = if(state.stamina.get() == 0.0f) 0.5 else 1.0
|
||||
var handling = vehicle.runtime.resolveDouble(settings.handlingExpr ?: globalJet.handlingExpr!!) * handlingDebuff
|
||||
var handling = vehicle.runtime.resolveDouble(settings.handlingExpr) * handlingDebuff
|
||||
//convert it to delta time
|
||||
handling *= (cappedDeltaTime)
|
||||
|
||||
@@ -407,7 +375,7 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
|
||||
|
||||
//Get handling in degrees per second
|
||||
val handlingDebuff = if(state.stamina.get() == 0.0f) 0.5 else 1.0
|
||||
var handling = vehicle.runtime.resolveDouble(settings.handlingExpr ?: globalJet.handlingExpr!!) * handlingDebuff
|
||||
var handling = vehicle.runtime.resolveDouble(settings.handlingExpr) * handlingDebuff
|
||||
|
||||
//convert it to delta time
|
||||
handling *= (cappedDeltaTime)
|
||||
@@ -483,12 +451,7 @@ class JetBehaviour : RidingBehaviour<JetSettings, JetState> {
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): Float {
|
||||
val maxDownwardForceTickCnt = 20.0f
|
||||
return when {
|
||||
state.noStamTickCnt.get() != 0 -> 1f - 0.2f*(state.noStamTickCnt.get() / maxDownwardForceTickCnt).coerceIn(0.0f,1.0f)
|
||||
state.boosting.get() -> 1.2f
|
||||
else -> 1.0f
|
||||
}
|
||||
return if (state.boosting.get()) 1.2f else 1.0f
|
||||
}
|
||||
|
||||
override fun useAngVelSmoothing(settings: JetSettings, state: JetState, vehicle: PokemonEntity): Boolean {
|
||||
@@ -561,70 +524,72 @@ class JetSettings : RidingBehaviourSettings {
|
||||
override val key = JetBehaviour.KEY
|
||||
override val stats = mutableMapOf<RidingStat, IntRange>()
|
||||
|
||||
var gravity: Expression? = null
|
||||
var gravity: Expression = "0".asExpression()
|
||||
private set
|
||||
|
||||
var deccelRate: Expression? = null
|
||||
var deccelRate: Expression = "0.005".asExpression()
|
||||
private set
|
||||
|
||||
// Mult to top speed in order to derive minSpeed
|
||||
var minSpeedFactor: Expression? = null
|
||||
var minSpeedFactor: Expression = "0.25".asExpression()
|
||||
private set
|
||||
|
||||
var handlingYawExpr: Expression? = null
|
||||
var handlingYawExpr: Expression = "q.get_ride_stats('SKILL', 'AIR', 50.0, 25.0)".asExpression()
|
||||
private set
|
||||
|
||||
// Make configurable by json
|
||||
var infiniteStamina: Expression? = null
|
||||
var infiniteStamina: Expression = "false".asExpression()
|
||||
private set
|
||||
|
||||
// Boost power. Mult for top speed and accel while boosting
|
||||
var jumpExpr: Expression? = null
|
||||
var jumpExpr: Expression = "q.get_ride_stats('JUMP', 'AIR', 2.0, 1.0)".asExpression()
|
||||
private set
|
||||
|
||||
// Turn rate in degrees per second
|
||||
var handlingExpr: Expression? = null
|
||||
var handlingExpr: Expression = "q.get_ride_stats('SKILL', 'AIR', 60.0, 20.0)".asExpression()
|
||||
private set
|
||||
// Top Speed in blocks per second
|
||||
var speedExpr: Expression? = null
|
||||
var speedExpr: Expression = "q.get_ride_stats('SPEED', 'AIR', 24.0, 4.0)".asExpression()
|
||||
private set
|
||||
// Seconds to get to top speed
|
||||
var accelerationExpr: Expression? = null
|
||||
var accelerationExpr: Expression =
|
||||
"q.get_ride_stats('ACCELERATION', 'AIR', 3.0, 8.0)".asExpression()
|
||||
private set
|
||||
// Time in seconds to drain full bar of stamina flying
|
||||
var staminaExpr: Expression? = null
|
||||
var staminaExpr: Expression = "q.get_ride_stats('STAMINA', 'AIR', 60.0, 4.0)".asExpression()
|
||||
private set
|
||||
|
||||
var rideSounds: RideSoundSettingsList = RideSoundSettingsList()
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeResourceLocation(key)
|
||||
buffer.writeRidingStats(stats)
|
||||
rideSounds.encode(buffer)
|
||||
buffer.writeNullableExpression(gravity)
|
||||
buffer.writeNullableExpression(deccelRate)
|
||||
buffer.writeNullableExpression(minSpeedFactor)
|
||||
buffer.writeNullableExpression(handlingYawExpr)
|
||||
buffer.writeNullableExpression(infiniteStamina)
|
||||
buffer.writeNullableExpression(jumpExpr)
|
||||
buffer.writeNullableExpression(handlingExpr)
|
||||
buffer.writeNullableExpression(speedExpr)
|
||||
buffer.writeNullableExpression(accelerationExpr)
|
||||
buffer.writeNullableExpression(staminaExpr)
|
||||
buffer.writeExpression(gravity)
|
||||
buffer.writeExpression(deccelRate)
|
||||
buffer.writeExpression(minSpeedFactor)
|
||||
buffer.writeExpression(handlingYawExpr)
|
||||
buffer.writeExpression(infiniteStamina)
|
||||
buffer.writeExpression(jumpExpr)
|
||||
buffer.writeExpression(handlingExpr)
|
||||
buffer.writeExpression(speedExpr)
|
||||
buffer.writeExpression(accelerationExpr)
|
||||
buffer.writeExpression(staminaExpr)
|
||||
}
|
||||
|
||||
override fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
stats.putAll(buffer.readRidingStats())
|
||||
rideSounds = RideSoundSettingsList.decode(buffer)
|
||||
gravity = buffer.readNullableExpression()
|
||||
deccelRate = buffer.readNullableExpression()
|
||||
minSpeedFactor = buffer.readNullableExpression()
|
||||
handlingYawExpr = buffer.readNullableExpression()
|
||||
infiniteStamina = buffer.readNullableExpression()
|
||||
jumpExpr = buffer.readNullableExpression()
|
||||
handlingExpr = buffer.readNullableExpression()
|
||||
speedExpr = buffer.readNullableExpression()
|
||||
accelerationExpr = buffer.readNullableExpression()
|
||||
staminaExpr = buffer.readNullableExpression()
|
||||
gravity = buffer.readExpression()
|
||||
deccelRate = buffer.readExpression()
|
||||
minSpeedFactor = buffer.readExpression()
|
||||
handlingYawExpr = buffer.readExpression()
|
||||
infiniteStamina = buffer.readExpression()
|
||||
jumpExpr = buffer.readExpression()
|
||||
handlingExpr = buffer.readExpression()
|
||||
speedExpr = buffer.readExpression()
|
||||
accelerationExpr = buffer.readExpression()
|
||||
staminaExpr = buffer.readExpression()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -635,7 +600,6 @@ class JetState : RidingBehaviourState() {
|
||||
var boosting = ridingState(false, Side.BOTH)
|
||||
var boostIsToggleable = ridingState(false, Side.BOTH)
|
||||
var canSpeedBurst = ridingState(false, Side.BOTH)
|
||||
var noStamTickCnt = ridingState(0, Side.CLIENT) // Value that is increased for every tick you are out of stamina
|
||||
|
||||
override fun encode(buffer: FriendlyByteBuf) {
|
||||
super.encode(buffer)
|
||||
@@ -662,7 +626,6 @@ class JetState : RidingBehaviourState() {
|
||||
boosting.set(false, forced = true)
|
||||
boostIsToggleable.set(false, forced = true)
|
||||
canSpeedBurst.set(true, forced = true)
|
||||
noStamTickCnt.set(0, forced = true)
|
||||
}
|
||||
|
||||
override fun copy() = JetState().also {
|
||||
|
||||
+32
-46
@@ -10,7 +10,6 @@ package com.cobblemon.mod.common.api.riding.behaviour.types.air
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.bedrockk.molang.runtime.MoLangMath.lerp
|
||||
import com.cobblemon.mod.common.CobblemonRideSettings
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.*
|
||||
import com.cobblemon.mod.common.api.riding.posing.PoseOption
|
||||
@@ -41,8 +40,6 @@ class RocketBehaviour : RidingBehaviour<RocketSettings, RocketState> {
|
||||
}
|
||||
|
||||
override val key = KEY
|
||||
val globalRocket: RocketSettings
|
||||
get() = CobblemonRideSettings.rocket
|
||||
|
||||
override fun getRidingStyle(settings: RocketSettings, state: RocketState): RidingStyle {
|
||||
return RidingStyle.AIR
|
||||
@@ -87,7 +84,7 @@ class RocketBehaviour : RidingBehaviour<RocketSettings, RocketState> {
|
||||
driver: Player
|
||||
): Float {
|
||||
// Use this as a "tick" function and check to see if the driver is "boosting"
|
||||
if (vehicle.level().isClientSide) {
|
||||
if(vehicle.level().isClientSide) {
|
||||
handleBoosting(settings, state, vehicle, driver)
|
||||
tickStamina(settings, state, vehicle, driver)
|
||||
}
|
||||
@@ -127,14 +124,10 @@ class RocketBehaviour : RidingBehaviour<RocketSettings, RocketState> {
|
||||
) {
|
||||
val stam = state.stamina.get()
|
||||
|
||||
if (vehicle.runtime.resolveBoolean(settings.infiniteStamina ?: globalRocket.infiniteStamina!!)) {
|
||||
return
|
||||
}
|
||||
|
||||
// Grab the boost time in seconds and convert to ticks. Then calculate the drain rate as inversely
|
||||
// proportional to the number of ticks of boost thus making a full boost take x ticks
|
||||
// in short: "Stamina drains slower at higher values and also replenishes slower"
|
||||
val boostTime = vehicle.runtime.resolveDouble(settings.staminaExpr ?: globalRocket.staminaExpr!!) * 20.0f
|
||||
val boostTime = vehicle.runtime.resolveDouble(settings.staminaExpr) * 20.0f
|
||||
val stamDrainRate = (1.0f / boostTime).toFloat()
|
||||
|
||||
val newStam = if(state.boosting.get() || driver.jumping) max(0.0f,stam - stamDrainRate) else stam
|
||||
@@ -186,13 +179,13 @@ class RocketBehaviour : RidingBehaviour<RocketSettings, RocketState> {
|
||||
|
||||
var newMomentum = state.turnMomentum.get().toDouble()
|
||||
// Degrees per tick
|
||||
val maxTurnMomentum = vehicle.runtime.resolveDouble(settings.maxTurnRate ?: globalRocket.maxTurnRate!!) / 20.0f
|
||||
val maxTurnMomentum = vehicle.runtime.resolveDouble(settings.maxTurnRate) / 20.0f
|
||||
// Turn rate increase per tick. Based off number of seconds to get to max turn rate
|
||||
val turningAcceleration = maxTurnMomentum / (vehicle.runtime.resolveDouble(settings.handlingExpr ?: globalRocket.handlingExpr!!) * 20.0f)
|
||||
val turningAcceleration = maxTurnMomentum / (vehicle.runtime.resolveDouble(settings.handlingExpr) * 20.0f)
|
||||
val turnInput = (driver.xxa *-1.0f) * turningAcceleration
|
||||
|
||||
// Base boost stats off of normal turning stats
|
||||
val boostHandlingMod = vehicle.runtime.resolveDouble(settings.boostHandlingMod ?: globalRocket.boostHandlingMod!!)
|
||||
val boostHandlingMod = vehicle.runtime.resolveDouble(settings.boostHandlingMod)
|
||||
val boostMaxTurnMomentum = maxTurnMomentum * boostHandlingMod
|
||||
val boostTurnInput = turnInput * boostHandlingMod
|
||||
|
||||
@@ -237,9 +230,9 @@ class RocketBehaviour : RidingBehaviour<RocketSettings, RocketState> {
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): Vec3 {
|
||||
val topSpeed = vehicle.runtime.resolveDouble(settings.speedExpr ?: globalRocket.speedExpr!!)
|
||||
val accel = vehicle.runtime.resolveDouble(settings.accelerationExpr ?: globalRocket.accelerationExpr!!)
|
||||
val jump = vehicle.runtime.resolveDouble(settings.jumpExpr ?: globalRocket.jumpExpr!!)
|
||||
val topSpeed = vehicle.runtime.resolveDouble(settings.speedExpr)
|
||||
val accel = vehicle.runtime.resolveDouble(settings.accelerationExpr)
|
||||
val jump = vehicle.runtime.resolveDouble(settings.jumpExpr)
|
||||
|
||||
var newVelocity = vehicle.deltaMovement
|
||||
|
||||
@@ -263,7 +256,7 @@ class RocketBehaviour : RidingBehaviour<RocketSettings, RocketState> {
|
||||
(newVelocity.z + (accel * forwardInput.toDouble())))
|
||||
|
||||
} else if ((state.boosting.get())) {
|
||||
val boostMod = vehicle.runtime.resolveDouble(settings.boostSpeedMod ?: globalRocket.boostSpeedMod!!)
|
||||
val boostMod = vehicle.runtime.resolveDouble(settings.boostSpeedMod)
|
||||
val boostSpeed = topSpeed * boostMod
|
||||
val boostAccel = if(newVelocity.length() < boostSpeed) accel * (boostMod/1.5) else 0.0
|
||||
val forwardInput = 1.0f
|
||||
@@ -405,8 +398,8 @@ class RocketBehaviour : RidingBehaviour<RocketSettings, RocketState> {
|
||||
driver: Player
|
||||
): Float {
|
||||
if (state.boosting.get()) {
|
||||
val topSpeed = vehicle.runtime.resolveDouble(settings.speedExpr ?: globalRocket.speedExpr!!)
|
||||
val boostMod = vehicle.runtime.resolveDouble(settings.boostSpeedMod ?: globalRocket.boostSpeedMod!!)
|
||||
val topSpeed = vehicle.runtime.resolveDouble(settings.speedExpr)
|
||||
val boostMod = vehicle.runtime.resolveDouble(settings.boostSpeedMod)
|
||||
val normalizedBoostSpeed = RidingBehaviour.scaleToRange(state.rideVelocity.get().length(), topSpeed, topSpeed * boostMod)
|
||||
return 1.0f + normalizedBoostSpeed.pow(2).toFloat() * 0.2f
|
||||
} else {
|
||||
@@ -506,67 +499,60 @@ class RocketSettings : RidingBehaviourSettings {
|
||||
override val key = RocketBehaviour.KEY
|
||||
override val stats = mutableMapOf<RidingStat, IntRange>()
|
||||
|
||||
var infiniteStamina: Expression? = null
|
||||
private set
|
||||
// Boost multiplier for speed
|
||||
var boostSpeedMod: Expression? = null
|
||||
var boostSpeedMod: Expression = "5.0".asExpression()
|
||||
private set
|
||||
|
||||
// Boost multiplier for handling
|
||||
var boostHandlingMod: Expression? = null
|
||||
var boostHandlingMod: Expression = "0.3".asExpression()
|
||||
private set
|
||||
|
||||
// Max turn rate in degrees per second
|
||||
var maxTurnRate: Expression? = null
|
||||
var maxTurnRate: Expression = "100.0".asExpression()
|
||||
private set
|
||||
|
||||
var speedExpr: Expression? = null
|
||||
var speedExpr: Expression = "q.get_ride_stats('SPEED', 'AIR', 1.2, 0.6)".asExpression()
|
||||
private set
|
||||
|
||||
// Max accel is a whole 1.0 in 1 second. The conversion in the function below is to convert seconds to ticks
|
||||
var accelerationExpr: Expression? = null
|
||||
var accelerationExpr: Expression =
|
||||
"q.get_ride_stats('ACCELERATION', 'AIR', (1.0 / (20.0 * 1.5)), (1.0 / (20.0 * 3.0))) * 0.5".asExpression()
|
||||
private set
|
||||
|
||||
// air time in seconds
|
||||
var staminaExpr: Expression? = null
|
||||
var staminaExpr: Expression = "q.get_ride_stats('STAMINA', 'AIR', 20.0, 10.0)".asExpression()
|
||||
private set
|
||||
|
||||
var jumpExpr: Expression? = null
|
||||
var jumpExpr: Expression = "q.get_ride_stats('JUMP', 'AIR', 2.0, 1.0)".asExpression()
|
||||
private set
|
||||
|
||||
// How long it takes to get to max turn rate from rest (in seconds)
|
||||
var handlingExpr: Expression? = null
|
||||
var handlingExpr: Expression = "q.get_ride_stats('SKILL', 'AIR', 0.5, 3.0)".asExpression()
|
||||
private set
|
||||
|
||||
var rideSounds: RideSoundSettingsList = RideSoundSettingsList()
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeResourceLocation(key)
|
||||
buffer.writeRidingStats(stats)
|
||||
rideSounds.encode(buffer)
|
||||
buffer.writeNullableExpression(infiniteStamina)
|
||||
buffer.writeNullableExpression(boostSpeedMod)
|
||||
buffer.writeNullableExpression(boostHandlingMod)
|
||||
buffer.writeNullableExpression(maxTurnRate)
|
||||
buffer.writeNullableExpression(speedExpr)
|
||||
buffer.writeNullableExpression(accelerationExpr)
|
||||
buffer.writeNullableExpression(staminaExpr)
|
||||
buffer.writeNullableExpression(jumpExpr)
|
||||
buffer.writeNullableExpression(handlingExpr)
|
||||
buffer.writeExpression(speedExpr)
|
||||
buffer.writeExpression(accelerationExpr)
|
||||
buffer.writeExpression(staminaExpr)
|
||||
buffer.writeExpression(jumpExpr)
|
||||
buffer.writeExpression(handlingExpr)
|
||||
}
|
||||
|
||||
override fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
stats.putAll(buffer.readRidingStats())
|
||||
rideSounds = RideSoundSettingsList.decode(buffer)
|
||||
infiniteStamina = buffer.readNullableExpression()
|
||||
boostSpeedMod = buffer.readNullableExpression()
|
||||
boostHandlingMod = buffer.readNullableExpression()
|
||||
maxTurnRate = buffer.readNullableExpression()
|
||||
speedExpr = buffer.readNullableExpression()
|
||||
accelerationExpr = buffer.readNullableExpression()
|
||||
staminaExpr = buffer.readNullableExpression()
|
||||
jumpExpr = buffer.readNullableExpression()
|
||||
handlingExpr = buffer.readNullableExpression()
|
||||
speedExpr = buffer.readExpression()
|
||||
accelerationExpr = buffer.readExpression()
|
||||
staminaExpr = buffer.readExpression()
|
||||
jumpExpr = buffer.readExpression()
|
||||
handlingExpr = buffer.readExpression()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class RocketState : RidingBehaviourState() {
|
||||
|
||||
+1
-2
@@ -387,10 +387,9 @@ open class CompositeSettings : RidingBehaviourSettings {
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeRidingStats(stats)
|
||||
buffer.writeResourceLocation(key)
|
||||
buffer.writeResourceLocation(transitionStrategy)
|
||||
buffer.writeResourceLocation(defaultBehaviour.key)
|
||||
defaultBehaviour.encode(buffer)
|
||||
buffer.writeResourceLocation(alternateBehaviour.key)
|
||||
alternateBehaviour.encode(buffer)
|
||||
}
|
||||
|
||||
|
||||
-4
@@ -41,10 +41,6 @@ interface CompositeRidingStrategy<T : CompositeSettings> {
|
||||
toState: RidingBehaviourState,
|
||||
toSettings: RidingBehaviourSettings
|
||||
) {
|
||||
if (vehicle.level().isClientSide) {
|
||||
val fromSettings = if (settings.defaultBehaviour == toSettings) settings.alternateBehaviour else settings.defaultBehaviour
|
||||
|
||||
}
|
||||
toState.stamina.set(fromState.stamina.get())
|
||||
toState.rideVelocity.set(fromState.rideVelocity.get())
|
||||
fromState.reset()
|
||||
|
||||
+39
-70
@@ -9,34 +9,16 @@
|
||||
package com.cobblemon.mod.common.api.riding.behaviour.types.land
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.cobblemon.mod.common.CobblemonRideSettings
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviour
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviourSettings
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviourState
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.Side
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.ridingState
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.*
|
||||
import com.cobblemon.mod.common.api.riding.posing.PoseOption
|
||||
import com.cobblemon.mod.common.api.riding.posing.PoseProvider
|
||||
import com.cobblemon.mod.common.api.riding.sound.RideSoundSettingsList
|
||||
import com.cobblemon.mod.common.api.riding.stats.RidingStat
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.blockPositionsAsListRounded
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.readNullableExpression
|
||||
import com.cobblemon.mod.common.util.readRidingStats
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.resolveDouble
|
||||
import com.cobblemon.mod.common.util.resolveFloat
|
||||
import com.cobblemon.mod.common.util.writeNullableExpression
|
||||
import com.cobblemon.mod.common.util.writeRidingStats
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.sign
|
||||
import kotlin.math.sqrt
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import com.cobblemon.mod.common.util.math.geometry.toRadians
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
@@ -49,6 +31,8 @@ import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.Vec2
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
import org.joml.Matrix3f
|
||||
import kotlin.math.*
|
||||
|
||||
class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
|
||||
companion object {
|
||||
@@ -56,8 +40,6 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
|
||||
}
|
||||
|
||||
override val key = KEY
|
||||
val globalHorse: HorseSettings
|
||||
get() = CobblemonRideSettings.horse
|
||||
|
||||
override fun getRidingStyle(settings: HorseSettings, state: HorseState): RidingStyle {
|
||||
return RidingStyle.LAND
|
||||
@@ -152,13 +134,8 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
|
||||
vehicle: PokemonEntity,
|
||||
) {
|
||||
val stam = state.stamina.get()
|
||||
|
||||
if (vehicle.runtime.resolveBoolean(settings.infiniteStamina ?: globalHorse.infiniteStamina!!)) {
|
||||
return
|
||||
}
|
||||
|
||||
var newStam = stam
|
||||
val stamDrainRate = (1.0f / vehicle.runtime.resolveDouble(settings.staminaExpr ?: globalHorse.staminaExpr!!)).toFloat() / 20.0f
|
||||
val stamDrainRate = (1.0f / vehicle.runtime.resolveDouble(settings.staminaExpr)).toFloat() / 20.0f
|
||||
|
||||
if (state.sprinting.get()) {
|
||||
newStam = max(0.0f,stam - stamDrainRate)
|
||||
@@ -208,10 +185,10 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
|
||||
vehicle: PokemonEntity,
|
||||
driver: LivingEntity
|
||||
): Float {
|
||||
val topSpeed = vehicle.runtime.resolveDouble(settings.speedExpr ?: globalHorse.speedExpr!!)
|
||||
val handling = vehicle.runtime.resolveDouble(settings.handlingExpr ?: globalHorse.handlingExpr!!)
|
||||
val topSpeed = vehicle.runtime.resolveDouble(settings.speedExpr)
|
||||
val handling = vehicle.runtime.resolveDouble(settings.handlingExpr)
|
||||
val walkHandlingBoost = 5
|
||||
val maxYawDiff = vehicle.runtime.resolveFloat(settings.lookYawLimit ?: globalHorse.lookYawLimit!!)
|
||||
val maxYawDiff = vehicle.runtime.resolveFloat(settings.lookYawLimit)
|
||||
|
||||
// Normalize the current rotation diff
|
||||
val rotDiff = Mth.wrapDegrees(driver.yRot - vehicle.yRot).coerceIn(-maxYawDiff,maxYawDiff)
|
||||
@@ -255,13 +232,13 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): Vec3 {
|
||||
val canSprint = vehicle.runtime.resolveBoolean(settings.canSprint ?: globalHorse.canSprint!!)
|
||||
val canJump = vehicle.runtime.resolveBoolean(settings.canJump ?: globalHorse.canJump!!)
|
||||
val jumpForce = vehicle.runtime.resolveDouble(settings.jumpExpr ?: globalHorse.jumpExpr!!) * 0.75
|
||||
val rideTopSpeed = vehicle.runtime.resolveDouble(settings.speedExpr ?: globalHorse.speedExpr!!)
|
||||
val canSprint = vehicle.runtime.resolveBoolean(settings.canSprint)
|
||||
val canJump = vehicle.runtime.resolveBoolean(settings.canJump)
|
||||
val jumpForce = vehicle.runtime.resolveDouble(settings.jumpExpr) * 0.75
|
||||
val rideTopSpeed = vehicle.runtime.resolveDouble(settings.speedExpr)
|
||||
val walkSpeed = getWalkSpeed(vehicle)
|
||||
val topSpeed = if(canSprint && state.sprinting.get()) rideTopSpeed else walkSpeed
|
||||
val accel = topSpeed / (vehicle.runtime.resolveDouble(settings.accelerationExpr ?: globalHorse.accelerationExpr!!) * 20.0)
|
||||
val accel = topSpeed / (vehicle.runtime.resolveDouble(settings.accelerationExpr) * 20.0)
|
||||
var activeInput = false
|
||||
|
||||
/******************************************************
|
||||
@@ -294,7 +271,7 @@ class HorseBehaviour : RidingBehaviour<HorseSettings, HorseState> {
|
||||
|
||||
// If on a tight turn then do not speed up past half of top speed in order to turn quicker
|
||||
// Also determine how fast to be slowing down based on how far turned you are
|
||||
val lookYawLimit = vehicle.runtime.resolveFloat(settings.lookYawLimit ?: globalHorse.lookYawLimit!!)
|
||||
val lookYawLimit = vehicle.runtime.resolveFloat(settings.lookYawLimit)
|
||||
val percOfMaxTurnSpeed = abs(Mth.wrapDegrees(driver.yRot - vehicle.yRot) / lookYawLimit) * 100.0f
|
||||
val turnPercThresh = 0.0f
|
||||
val s = min(((percOfMaxTurnSpeed - turnPercThresh) / (100.0f - turnPercThresh)).pow(1),1.0f)
|
||||
@@ -536,67 +513,59 @@ class HorseSettings : RidingBehaviourSettings {
|
||||
override val key = HorseBehaviour.KEY
|
||||
override val stats = mutableMapOf<RidingStat, IntRange>()
|
||||
|
||||
var infiniteStamina: Expression? = null
|
||||
private set
|
||||
var canJump: Expression? = null
|
||||
var canJump = "true".asExpression()
|
||||
private set
|
||||
|
||||
var canSprint: Expression? = null
|
||||
var canSprint = "true".asExpression()
|
||||
private set
|
||||
|
||||
var lookYawLimit: Expression? = null
|
||||
var lookYawLimit = "90.0f".asExpression()
|
||||
private set
|
||||
|
||||
var speedExpr: Expression? = null
|
||||
var speedExpr: Expression = "q.get_ride_stats('SPEED', 'LAND', 1.0, 0.4)".asExpression()
|
||||
private set
|
||||
|
||||
// Max accel is a whole 1.0 in 1 second. The conversion in the function below is to convert seconds to ticks
|
||||
var accelerationExpr: Expression? = null
|
||||
var accelerationExpr: Expression =
|
||||
"q.get_ride_stats('ACCELERATION', 'LAND', 0.5, 2.0)".asExpression()
|
||||
private set
|
||||
|
||||
// Between 30 seconds and 10 seconds at the lowest when at full speed.
|
||||
var staminaExpr: Expression? = null
|
||||
var staminaExpr: Expression = "q.get_ride_stats('STAMINA', 'LAND', 30.0, 10.0)".asExpression()
|
||||
private set
|
||||
|
||||
//Between a one block jump and a six block jump
|
||||
var jumpExpr: Expression? = null
|
||||
var jumpExpr: Expression = "q.get_ride_stats('JUMP', 'LAND', 1.0, 0.38)".asExpression()
|
||||
private set
|
||||
|
||||
var handlingExpr: Expression? = null
|
||||
var handlingExpr: Expression = "q.get_ride_stats('SKILL', 'LAND', 180.0, 40.0)".asExpression()
|
||||
private set
|
||||
|
||||
var rideSounds: RideSoundSettingsList = RideSoundSettingsList()
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeResourceLocation(key)
|
||||
buffer.writeRidingStats(stats)
|
||||
rideSounds.encode(buffer)
|
||||
buffer.writeNullableExpression(infiniteStamina)
|
||||
buffer.writeNullableExpression(canJump)
|
||||
buffer.writeNullableExpression(canSprint)
|
||||
buffer.writeNullableExpression(lookYawLimit)
|
||||
buffer.writeNullableExpression(speedExpr)
|
||||
buffer.writeNullableExpression(accelerationExpr)
|
||||
buffer.writeNullableExpression(staminaExpr)
|
||||
buffer.writeNullableExpression(jumpExpr)
|
||||
buffer.writeNullableExpression(handlingExpr)
|
||||
buffer.writeNullableExpression(canJump)
|
||||
buffer.writeNullableExpression(canSprint)
|
||||
buffer.writeExpression(speedExpr)
|
||||
buffer.writeExpression(accelerationExpr)
|
||||
buffer.writeExpression(staminaExpr)
|
||||
buffer.writeExpression(jumpExpr)
|
||||
buffer.writeExpression(handlingExpr)
|
||||
buffer.writeExpression(canJump)
|
||||
buffer.writeExpression(canSprint)
|
||||
}
|
||||
|
||||
override fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
stats.putAll(buffer.readRidingStats())
|
||||
rideSounds = RideSoundSettingsList.decode(buffer)
|
||||
infiniteStamina = buffer.readNullableExpression()
|
||||
canJump = buffer.readNullableExpression()
|
||||
canSprint = buffer.readNullableExpression()
|
||||
lookYawLimit = buffer.readNullableExpression()
|
||||
speedExpr = buffer.readNullableExpression()
|
||||
accelerationExpr = buffer.readNullableExpression()
|
||||
staminaExpr = buffer.readNullableExpression()
|
||||
jumpExpr = buffer.readNullableExpression()
|
||||
handlingExpr = buffer.readNullableExpression()
|
||||
canJump = buffer.readNullableExpression()
|
||||
canSprint = buffer.readNullableExpression()
|
||||
speedExpr = buffer.readExpression()
|
||||
accelerationExpr = buffer.readExpression()
|
||||
staminaExpr = buffer.readExpression()
|
||||
jumpExpr = buffer.readExpression()
|
||||
handlingExpr = buffer.readExpression()
|
||||
canJump = buffer.readExpression()
|
||||
canSprint = buffer.readExpression()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+28
-54
@@ -10,36 +10,18 @@ package com.cobblemon.mod.common.api.riding.behaviour.types.land
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.bedrockk.molang.runtime.MoLangMath.lerp
|
||||
import com.cobblemon.mod.common.CobblemonRideSettings
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.OrientationControllable
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviour
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviourSettings
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviourState
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.Side
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.SidedRidingState
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.ridingState
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.*
|
||||
import com.cobblemon.mod.common.api.riding.posing.PoseOption
|
||||
import com.cobblemon.mod.common.api.riding.posing.PoseProvider
|
||||
import com.cobblemon.mod.common.api.riding.sound.RideSoundSettingsList
|
||||
import com.cobblemon.mod.common.api.riding.stats.RidingStat
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.blockPositionsAsListRounded
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import com.cobblemon.mod.common.util.math.geometry.toRadians
|
||||
import com.cobblemon.mod.common.util.readNullableExpression
|
||||
import com.cobblemon.mod.common.util.readRidingStats
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.resolveDouble
|
||||
import com.cobblemon.mod.common.util.resolveFloat
|
||||
import com.cobblemon.mod.common.util.writeNullableExpression
|
||||
import com.cobblemon.mod.common.util.writeRidingStats
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.sign
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
@@ -50,6 +32,12 @@ import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.Vec2
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
import org.joml.Matrix3f
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.sign
|
||||
|
||||
class MinekartBehaviour : RidingBehaviour<MinekartSettings, MinekartState> {
|
||||
companion object {
|
||||
@@ -57,8 +45,6 @@ class MinekartBehaviour : RidingBehaviour<MinekartSettings, MinekartState> {
|
||||
}
|
||||
|
||||
override val key = KEY
|
||||
val globalMinekart: MinekartSettings
|
||||
get() = CobblemonRideSettings.minekart
|
||||
|
||||
override fun getRidingStyle(settings: MinekartSettings, state: MinekartState): RidingStyle {
|
||||
return RidingStyle.LAND
|
||||
@@ -98,7 +84,7 @@ class MinekartBehaviour : RidingBehaviour<MinekartSettings, MinekartState> {
|
||||
driver: Player
|
||||
): Float {
|
||||
|
||||
val boostMax = vehicle.runtime.resolveFloat(settings.boostLimit ?: globalMinekart.boostLimit!!)
|
||||
val boostMax = vehicle.runtime.resolveFloat(settings.boostLimit)
|
||||
//TODO: should this be by how much turn has accumulated or simply time turning... or both?
|
||||
val boostPerSecond = 20.0f
|
||||
val boostLoss = 40.0f
|
||||
@@ -156,8 +142,8 @@ class MinekartBehaviour : RidingBehaviour<MinekartSettings, MinekartState> {
|
||||
var newMomentum = state.turnMomentum.get().toDouble()
|
||||
|
||||
//TODO: maybe tie this to max turnspeeds rather than the turn acceleration
|
||||
val topSpeed = vehicle.runtime.resolveDouble(settings.speedExpr ?: globalMinekart.speedExpr!!)
|
||||
val turningAcceleration = (vehicle.runtime.resolveDouble(settings.handlingExpr ?: globalMinekart.handlingExpr!!) * 1.5 / 20.0f) / 20.0f * 4.0
|
||||
val topSpeed = vehicle.runtime.resolveDouble(settings.speedExpr)
|
||||
val turningAcceleration = (vehicle.runtime.resolveDouble(settings.handlingExpr) * 1.5 / 20.0f) / 20.0f * 4.0
|
||||
val turnInput = (driver.xxa *-1.0f) * turningAcceleration
|
||||
val driftInput = turnInput * 0.25f
|
||||
|
||||
@@ -216,9 +202,9 @@ class MinekartBehaviour : RidingBehaviour<MinekartSettings, MinekartState> {
|
||||
): Vec3 {
|
||||
|
||||
// Check to see if the ride should be walking or sprinting
|
||||
val rideTopSpeed = vehicle.runtime.resolveDouble(settings.speedExpr ?: globalMinekart.speedExpr!!) * 0.6 * 2.0
|
||||
val rideTopSpeed = vehicle.runtime.resolveDouble(settings.speedExpr) * 0.6 * 2.0
|
||||
val topSpeed = if (state.drifting.get()) rideTopSpeed * 0.7 else rideTopSpeed
|
||||
val accel = vehicle.runtime.resolveDouble(settings.accelerationExpr ?: globalMinekart.accelerationExpr!!) * 0.3 * 3 * 2.0
|
||||
val accel = vehicle.runtime.resolveDouble(settings.accelerationExpr) * 0.3 * 3 * 2.0
|
||||
val driftAngle = 20.0f
|
||||
|
||||
//Align the direction of this vector with the vehicles current heading.
|
||||
@@ -341,7 +327,7 @@ class MinekartBehaviour : RidingBehaviour<MinekartSettings, MinekartState> {
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): Boolean {
|
||||
return vehicle.runtime.resolveBoolean(settings.canJump ?: globalMinekart.canJump!!)
|
||||
return vehicle.runtime.resolveBoolean(settings.canJump)
|
||||
}
|
||||
|
||||
override fun setRideBar(
|
||||
@@ -461,57 +447,45 @@ class MinekartSettings : RidingBehaviourSettings {
|
||||
override val key = MinekartBehaviour.KEY
|
||||
override val stats = mutableMapOf<RidingStat, IntRange>()
|
||||
|
||||
var infiniteStamina: Expression? = null
|
||||
private set
|
||||
var canJump: Expression? = null
|
||||
var canJump = "true".asExpression()
|
||||
private set
|
||||
|
||||
var boostLimit: Expression? = null
|
||||
var boostLimit = "100.0f".asExpression()
|
||||
private set
|
||||
|
||||
var speedExpr: Expression? = null
|
||||
var speedExpr: Expression = "q.get_ride_stats('SPEED', 'LAND', 1.0, 0.3)".asExpression()
|
||||
private set
|
||||
|
||||
// Max accel is a whole 1.0 in 1 second. The conversion in the function below is to convert seconds to ticks
|
||||
var accelerationExpr: Expression? = null
|
||||
var accelerationExpr: Expression =
|
||||
"q.get_ride_stats('ACCELERATION', 'LAND', (1.0 / (20.0 * 1.5)), (1.0 / (20.0 * 5.0)))".asExpression()
|
||||
private set
|
||||
|
||||
var staminaExpr: Expression? = null
|
||||
var staminaExpr: Expression = "q.get_ride_stats('STAMINA', 'LAND', 30.0, 10.0)".asExpression()
|
||||
private set
|
||||
|
||||
//Between a one block jump and a ten block jump
|
||||
var jumpExpr: Expression? = null
|
||||
var jumpExpr: Expression = "q.get_ride_stats('JUMP', 'LAND', 10.0, 1.0)".asExpression()
|
||||
private set
|
||||
|
||||
var handlingExpr: Expression? = null
|
||||
var handlingExpr: Expression = "q.get_ride_stats('SKILL', 'LAND', 140.0, 20.0)".asExpression()
|
||||
private set
|
||||
|
||||
var rideSounds: RideSoundSettingsList = RideSoundSettingsList()
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeResourceLocation(key)
|
||||
buffer.writeRidingStats(stats)
|
||||
rideSounds.encode(buffer)
|
||||
buffer.writeNullableExpression(infiniteStamina)
|
||||
buffer.writeNullableExpression(canJump)
|
||||
buffer.writeNullableExpression(boostLimit)
|
||||
buffer.writeNullableExpression(speedExpr)
|
||||
buffer.writeNullableExpression(accelerationExpr)
|
||||
buffer.writeNullableExpression(staminaExpr)
|
||||
buffer.writeNullableExpression(jumpExpr)
|
||||
buffer.writeNullableExpression(handlingExpr)
|
||||
buffer.writeExpression(canJump)
|
||||
buffer.writeExpression(boostLimit)
|
||||
}
|
||||
|
||||
override fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
stats.putAll(buffer.readRidingStats())
|
||||
rideSounds = RideSoundSettingsList.decode(buffer)
|
||||
infiniteStamina = buffer.readNullableExpression()
|
||||
canJump = buffer.readNullableExpression()
|
||||
boostLimit = buffer.readNullableExpression()
|
||||
speedExpr = buffer.readNullableExpression()
|
||||
accelerationExpr = buffer.readNullableExpression()
|
||||
staminaExpr = buffer.readNullableExpression()
|
||||
jumpExpr = buffer.readNullableExpression()
|
||||
handlingExpr = buffer.readNullableExpression()
|
||||
canJump = buffer.readExpression()
|
||||
boostLimit = buffer.readExpression()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+38
-66
@@ -10,35 +10,18 @@ package com.cobblemon.mod.common.api.riding.behaviour.types.land
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.bedrockk.molang.runtime.MoLangMath.lerp
|
||||
import com.cobblemon.mod.common.CobblemonRideSettings
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.OrientationControllable
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviour
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviourSettings
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviourState
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.Side
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.SidedRidingState
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.ridingState
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.*
|
||||
import com.cobblemon.mod.common.api.riding.posing.PoseOption
|
||||
import com.cobblemon.mod.common.api.riding.posing.PoseProvider
|
||||
import com.cobblemon.mod.common.api.riding.sound.RideSoundSettingsList
|
||||
import com.cobblemon.mod.common.api.riding.stats.RidingStat
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.blockPositionsAsListRounded
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import com.cobblemon.mod.common.util.math.geometry.toRadians
|
||||
import com.cobblemon.mod.common.util.readNullableExpression
|
||||
import com.cobblemon.mod.common.util.readRidingStats
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.resolveDouble
|
||||
import com.cobblemon.mod.common.util.toVec3d
|
||||
import com.cobblemon.mod.common.util.writeNullableExpression
|
||||
import com.cobblemon.mod.common.util.writeRidingStats
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
import kotlin.math.sign
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
@@ -50,6 +33,10 @@ import net.minecraft.world.phys.Vec2
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
import org.joml.Matrix3f
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
import kotlin.math.sign
|
||||
|
||||
class VehicleBehaviour : RidingBehaviour<VehicleSettings, VehicleState> {
|
||||
companion object {
|
||||
@@ -57,8 +44,6 @@ class VehicleBehaviour : RidingBehaviour<VehicleSettings, VehicleState> {
|
||||
}
|
||||
|
||||
override val key = KEY
|
||||
val globalVehicle: VehicleSettings
|
||||
get() = CobblemonRideSettings.vehicle
|
||||
|
||||
override fun getRidingStyle(settings: VehicleSettings, state: VehicleState): RidingStyle {
|
||||
return RidingStyle.LAND
|
||||
@@ -141,7 +126,7 @@ class VehicleBehaviour : RidingBehaviour<VehicleSettings, VehicleState> {
|
||||
var newMomentum = state.turnMomentum.get().toDouble()
|
||||
|
||||
// Grab turningAcceleration and divide 20 twice to get
|
||||
val turningAcceleration = (vehicle.runtime.resolveDouble(settings.handlingExpr ?: globalVehicle.handlingExpr!!) * 1.5 / 20.0f) / 20.0f * 4.0
|
||||
val turningAcceleration = (vehicle.runtime.resolveDouble(settings.handlingExpr) * 1.5 / 20.0f) / 20.0f * 4.0
|
||||
val turnInput = (driver.xxa *-1.0f) * turningAcceleration
|
||||
|
||||
val maxTurnMomentum = 80.0f / 20.0f
|
||||
@@ -152,7 +137,7 @@ class VehicleBehaviour : RidingBehaviour<VehicleSettings, VehicleState> {
|
||||
|
||||
if(state.drifting.get() || state.inAir.get()) {
|
||||
if( newMomentum < driftMaxTurnMomentum) {
|
||||
driftTurnInput = driftTurnInput * (vehicle.deltaMovement.horizontalDistance() / vehicle.runtime.resolveDouble(settings.speedExpr ?: globalVehicle.speedExpr!!))
|
||||
driftTurnInput = driftTurnInput * (vehicle.deltaMovement.horizontalDistance() / vehicle.runtime.resolveDouble(settings.speedExpr))
|
||||
newMomentum += driftTurnInput
|
||||
}
|
||||
newMomentum = lerp(newMomentum, 0.0, 0.03)
|
||||
@@ -192,10 +177,10 @@ class VehicleBehaviour : RidingBehaviour<VehicleSettings, VehicleState> {
|
||||
|
||||
// Check to see if the ride should be walking or sprinting
|
||||
//val walkSpeed = getWalkSpeed(vehicle)
|
||||
val rideTopSpeed = vehicle.runtime.resolveDouble(settings.speedExpr ?: globalVehicle.speedExpr!!) * 0.6 * 2.0
|
||||
val rideTopSpeed = vehicle.runtime.resolveDouble(settings.speedExpr) * 0.6 * 2.0
|
||||
val topSpeed = if (state.drifting.get()) rideTopSpeed * 0.5 else rideTopSpeed
|
||||
|
||||
val accel = vehicle.runtime.resolveDouble(settings.accelerationExpr ?: globalVehicle.accelerationExpr!!) * 0.3 * 3 * 2.0
|
||||
val accel = vehicle.runtime.resolveDouble(settings.accelerationExpr) * 0.3 * 3 * 2.0
|
||||
|
||||
//Flag for determining if player is actively inputting
|
||||
var activeInput = false
|
||||
@@ -265,7 +250,7 @@ class VehicleBehaviour : RidingBehaviour<VehicleSettings, VehicleState> {
|
||||
}
|
||||
|
||||
//TODO: Change this so its tied to a jumping stat and representative of the amount of jumps
|
||||
val canJump = vehicle.runtime.resolveBoolean(settings.canJump ?: globalVehicle.canJump!!)
|
||||
val canJump = vehicle.runtime.resolveBoolean(settings.canJump)
|
||||
//Jump the thang!
|
||||
if (driver.jumping && vehicle.onGround() && canJump) {
|
||||
val jumpForce = 0.5
|
||||
@@ -311,7 +296,7 @@ class VehicleBehaviour : RidingBehaviour<VehicleSettings, VehicleState> {
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): Boolean {
|
||||
return vehicle.runtime.resolveBoolean(settings.canJump ?: globalVehicle.canJump!!)
|
||||
return vehicle.runtime.resolveBoolean(settings.canJump)
|
||||
}
|
||||
|
||||
override fun setRideBar(
|
||||
@@ -427,79 +412,66 @@ class VehicleSettings : RidingBehaviourSettings {
|
||||
override val key = VehicleBehaviour.KEY
|
||||
override val stats = mutableMapOf<RidingStat, IntRange>()
|
||||
|
||||
var infiniteStamina: Expression? = null
|
||||
var canJump = "true".asExpression()
|
||||
private set
|
||||
|
||||
var canJump: Expression? = null
|
||||
var speed = "0.3".asExpression()
|
||||
private set
|
||||
|
||||
var speed: Expression? = null
|
||||
var driveFactor = "1.0".asExpression()
|
||||
private set
|
||||
|
||||
var driveFactor: Expression? = null
|
||||
var reverseDriveFactor = "0.25".asExpression()
|
||||
private set
|
||||
|
||||
var reverseDriveFactor: Expression? = null
|
||||
var rotationSpeed = "45/20".asExpression()
|
||||
private set
|
||||
|
||||
var rotationSpeed: Expression? = null
|
||||
var lookYawLimit = "101".asExpression()
|
||||
private set
|
||||
|
||||
var lookYawLimit: Expression? = null
|
||||
private set
|
||||
|
||||
var speedExpr: Expression? = null
|
||||
var speedExpr: Expression = "q.get_ride_stats('SPEED', 'LAND', 1.0, 0.3)".asExpression()
|
||||
private set
|
||||
|
||||
// Max accel is a whole 1.0 in 1 second. The conversion in the function below is to convert seconds to ticks
|
||||
var accelerationExpr: Expression? = null
|
||||
var accelerationExpr: Expression =
|
||||
"q.get_ride_stats('ACCELERATION', 'LAND', (1.0 / (20.0 * 1.5)), (1.0 / (20.0 * 5.0)))".asExpression()
|
||||
private set
|
||||
|
||||
// Between 30 seconds and 10 seconds at the lowest when at full speed.
|
||||
var staminaExpr: Expression? = null
|
||||
var staminaExpr: Expression = "q.get_ride_stats('STAMINA', 'LAND', 30.0, 10.0)".asExpression()
|
||||
private set
|
||||
|
||||
//Between a one block jump and a ten block jump
|
||||
var jumpExpr: Expression? = null
|
||||
var jumpExpr: Expression = "q.get_ride_stats('JUMP', 'LAND', 10.0, 1.0)".asExpression()
|
||||
private set
|
||||
|
||||
var handlingExpr: Expression? = null
|
||||
var handlingExpr: Expression = "q.get_ride_stats('SKILL', 'LAND', 140.0, 20.0)".asExpression()
|
||||
private set
|
||||
|
||||
var rideSounds: RideSoundSettingsList = RideSoundSettingsList()
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeResourceLocation(key)
|
||||
buffer.writeRidingStats(stats)
|
||||
rideSounds.encode(buffer)
|
||||
buffer.writeNullableExpression(infiniteStamina)
|
||||
buffer.writeNullableExpression(canJump)
|
||||
buffer.writeNullableExpression(speed)
|
||||
buffer.writeNullableExpression(driveFactor)
|
||||
buffer.writeNullableExpression(reverseDriveFactor)
|
||||
buffer.writeNullableExpression(rotationSpeed)
|
||||
buffer.writeNullableExpression(lookYawLimit)
|
||||
buffer.writeNullableExpression(speedExpr)
|
||||
buffer.writeNullableExpression(accelerationExpr)
|
||||
buffer.writeNullableExpression(staminaExpr)
|
||||
buffer.writeNullableExpression(jumpExpr)
|
||||
buffer.writeNullableExpression(handlingExpr)
|
||||
buffer.writeExpression(canJump)
|
||||
buffer.writeExpression(speed)
|
||||
buffer.writeExpression(driveFactor)
|
||||
buffer.writeExpression(reverseDriveFactor)
|
||||
buffer.writeExpression(rotationSpeed)
|
||||
buffer.writeExpression(lookYawLimit)
|
||||
}
|
||||
|
||||
override fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
stats.putAll(buffer.readRidingStats())
|
||||
rideSounds = RideSoundSettingsList.decode(buffer)
|
||||
infiniteStamina = buffer.readNullableExpression()
|
||||
canJump = buffer.readNullableExpression()
|
||||
speed = buffer.readNullableExpression()
|
||||
driveFactor = buffer.readNullableExpression()
|
||||
reverseDriveFactor = buffer.readNullableExpression()
|
||||
rotationSpeed = buffer.readNullableExpression()
|
||||
lookYawLimit = buffer.readNullableExpression()
|
||||
speedExpr = buffer.readNullableExpression()
|
||||
accelerationExpr = buffer.readNullableExpression()
|
||||
staminaExpr = buffer.readNullableExpression()
|
||||
jumpExpr = buffer.readNullableExpression()
|
||||
handlingExpr = buffer.readNullableExpression()
|
||||
canJump = buffer.readExpression()
|
||||
speed = buffer.readExpression()
|
||||
driveFactor = buffer.readExpression()
|
||||
reverseDriveFactor = buffer.readExpression()
|
||||
rotationSpeed = buffer.readExpression()
|
||||
lookYawLimit = buffer.readExpression()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+30
-82
@@ -8,34 +8,16 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.riding.behaviour.types.liquid
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.cobblemon.mod.common.CobblemonRideSettings
|
||||
import com.cobblemon.mod.common.OrientationControllable
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviour
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviourSettings
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviourState
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.Side
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.ridingState
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.*
|
||||
import com.cobblemon.mod.common.api.riding.posing.PoseOption
|
||||
import com.cobblemon.mod.common.api.riding.posing.PoseProvider
|
||||
import com.cobblemon.mod.common.api.riding.sound.RideSoundSettingsList
|
||||
import com.cobblemon.mod.common.api.riding.stats.RidingStat
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.blockPositionsAsListRounded
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.readNullableExpression
|
||||
import com.cobblemon.mod.common.util.readRidingStats
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.resolveDouble
|
||||
import com.cobblemon.mod.common.util.resolveFloat
|
||||
import com.cobblemon.mod.common.util.writeNullableExpression
|
||||
import com.cobblemon.mod.common.util.writeRidingStats
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
import net.minecraft.core.BlockPos
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.Mth
|
||||
@@ -45,6 +27,9 @@ import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.Vec2
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
|
||||
class BoatBehaviour : RidingBehaviour<BoatSettings, BoatState> {
|
||||
companion object {
|
||||
@@ -52,8 +37,6 @@ class BoatBehaviour : RidingBehaviour<BoatSettings, BoatState> {
|
||||
}
|
||||
|
||||
override val key = KEY
|
||||
val globalBoat: BoatSettings
|
||||
get() = CobblemonRideSettings.boat
|
||||
|
||||
override fun getRidingStyle(settings: BoatSettings, state: BoatState): RidingStyle {
|
||||
return RidingStyle.LIQUID
|
||||
@@ -103,7 +86,7 @@ class BoatBehaviour : RidingBehaviour<BoatSettings, BoatState> {
|
||||
|
||||
if (!state.isVehicleSprinting.get()) {
|
||||
if (state.staminaBuffer.get() >= 20) {
|
||||
val staminaIncrease = vehicle.runtime.resolveDouble(settings.staminaIncreaseExpr ?: globalBoat.staminaIncreaseExpr!!)
|
||||
val staminaIncrease = vehicle.runtime.resolveDouble(settings.staminaIncreaseExpr)
|
||||
state.stamina.set(min(1.0f, state.stamina.get() + 0.01f * staminaIncrease.toFloat()))
|
||||
}
|
||||
}
|
||||
@@ -150,14 +133,14 @@ class BoatBehaviour : RidingBehaviour<BoatSettings, BoatState> {
|
||||
}
|
||||
|
||||
private fun applyVelocityFromInput(velocity: Vec3, vehicle: PokemonEntity, driver: Player, settings: BoatSettings, state: BoatState): Vec3 {
|
||||
val speed = vehicle.runtime.resolveDouble(settings.speedExpr ?: globalBoat.speedExpr!!)
|
||||
val acceleration = speed / (vehicle.runtime.resolveDouble(settings.accelerationExpr ?: globalBoat.accelerationExpr!!) * 20)
|
||||
val speed = vehicle.runtime.resolveDouble(settings.speedExpr)
|
||||
val acceleration = vehicle.runtime.resolveDouble(settings.accelerationExpr)
|
||||
|
||||
if (state.jumpBuffer.get() != -1 || !(vehicle.isInWater || vehicle.isUnderWater)) {
|
||||
return velocity
|
||||
}
|
||||
|
||||
val sprintModifier = vehicle.runtime.resolveDouble(settings.sprintSpeedModifier ?: globalBoat.sprintSpeedModifier!!)
|
||||
val sprintModifier = vehicle.runtime.resolveDouble(settings.sprintSpeedModifier)
|
||||
val activeSprintModifier = if (state.isVehicleSprinting.get() && hasStamina(state)) sprintModifier else 1.0
|
||||
val forwardInput = driver.zza.toDouble()
|
||||
val delta = when {
|
||||
@@ -180,34 +163,23 @@ class BoatBehaviour : RidingBehaviour<BoatSettings, BoatState> {
|
||||
if (!driver.jumping) return velocity // Not jumping
|
||||
if (state.jumpBuffer.get() != -1) return velocity // Already jumped very recently
|
||||
|
||||
val jumpStrength = vehicle.runtime.resolveDouble(settings.jumpStrengthExpr ?: globalBoat.jumpStrengthExpr!!)
|
||||
val jumpStrength = vehicle.runtime.resolveDouble(settings.jumpStrengthExpr)
|
||||
state.jumpBuffer.set(0)
|
||||
return Vec3(velocity.x, velocity.y + jumpStrength, velocity.z)
|
||||
}
|
||||
|
||||
private fun applyGravity(velocity: Vec3, vehicle: PokemonEntity, settings: BoatSettings, state: BoatState): Vec3 {
|
||||
if (state.jumpBuffer.get() == -1 && (vehicle.isInWater || vehicle.isUnderWater)) {
|
||||
if (shouldFloatHigher(vehicle, settings)) {
|
||||
return Vec3(velocity.x, 0.5, velocity.z)
|
||||
}
|
||||
else {
|
||||
return Vec3(velocity.x, 0.0, velocity.z)
|
||||
}
|
||||
val verticalVelocity = if (vehicle.isUnderWater) 0.5 else 0.0
|
||||
return Vec3(velocity.x, verticalVelocity, velocity.z)
|
||||
}
|
||||
val terminalVelocity = vehicle.runtime.resolveDouble(settings.terminalVelocity ?: globalBoat.terminalVelocity!!)
|
||||
val terminalVelocity = vehicle.runtime.resolveDouble(settings.terminalVelocity)
|
||||
val gravity = (9.8 / ( 20.0)) * 0.2
|
||||
return Vec3(velocity.x, max(velocity.y - gravity, terminalVelocity), velocity.z)
|
||||
}
|
||||
|
||||
private fun shouldFloatHigher(vehicle: PokemonEntity, settings: BoatSettings): Boolean {
|
||||
val surfaceOffset = vehicle.runtime.resolveFloat(settings.surfaceLevelOffset ?: globalBoat.surfaceLevelOffset!!)
|
||||
val blockPos = BlockPos.containing(vehicle.x, vehicle.eyeY + surfaceOffset, vehicle.z)
|
||||
val fluidState = vehicle.level().getFluidState(blockPos)
|
||||
return !fluidState.isEmpty
|
||||
}
|
||||
|
||||
private fun applyStrafeRotation(vehicle: PokemonEntity, driver: Player, settings: BoatSettings, state: BoatState) {
|
||||
val skillModifier = vehicle.runtime.resolveDouble(settings.rotationSpeedModifierExpr ?: globalBoat.rotationSpeedModifierExpr!!)
|
||||
val skillModifier = vehicle.runtime.resolveDouble(settings.rotationspeedModifierExpr)
|
||||
val strafe = driver.xxa
|
||||
if (abs(strafe) > 0) {
|
||||
val increase = if (strafe > 0) -1 else 1
|
||||
@@ -220,10 +192,7 @@ class BoatBehaviour : RidingBehaviour<BoatSettings, BoatState> {
|
||||
}
|
||||
|
||||
private fun consumeStamina(vehicle: PokemonEntity, driver: Player, settings: BoatSettings, state: BoatState, drain: Float) {
|
||||
val staminaModifier = vehicle.runtime.resolveFloat(settings.staminaDecreaseExpr ?: globalBoat.staminaDecreaseExpr!!)
|
||||
if (staminaModifier == 0F) {
|
||||
return
|
||||
}
|
||||
val staminaModifier = vehicle.runtime.resolveFloat(settings.staminaDecreaseExpr)
|
||||
state.stamina.set(max(0f, state.stamina.get() - drain / staminaModifier))
|
||||
if (state.stamina.get() == 0f) {
|
||||
state.isVehicleSprinting.set(false)
|
||||
@@ -329,7 +298,7 @@ class BoatBehaviour : RidingBehaviour<BoatSettings, BoatState> {
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): Float {
|
||||
val sprintFov = vehicle.runtime.resolveFloat(settings.sprintFovModifier ?: globalBoat.sprintFovModifier!!)
|
||||
val sprintFov = vehicle.runtime.resolveFloat(settings.sprintFovModifier)
|
||||
return if (state.isVehicleSprinting.get()) sprintFov else 1.0f
|
||||
}
|
||||
|
||||
@@ -374,7 +343,7 @@ class BoatBehaviour : RidingBehaviour<BoatSettings, BoatState> {
|
||||
state: BoatState,
|
||||
vehicle: PokemonEntity
|
||||
): Boolean {
|
||||
return vehicle.runtime.resolveBoolean(settings.rotatePokemonHead ?: globalBoat.rotatePokemonHead!!)
|
||||
return vehicle.runtime.resolveBoolean(settings.rotatePokemonHead)
|
||||
}
|
||||
|
||||
override fun shouldRotateRiderHead(
|
||||
@@ -404,67 +373,46 @@ class BoatSettings : RidingBehaviourSettings {
|
||||
override val stats = mutableMapOf<RidingStat, IntRange>()
|
||||
var rideSounds: RideSoundSettingsList = RideSoundSettingsList()
|
||||
|
||||
var terminalVelocity: Expression? = null
|
||||
var terminalVelocity = "-2.0".asExpression()
|
||||
private set
|
||||
|
||||
var rotatePokemonHead: Expression? = null
|
||||
var rotatePokemonHead = "true".asExpression()
|
||||
private set
|
||||
|
||||
var staminaIncreaseExpr: Expression? = null
|
||||
var staminaIncreaseExpr = "q.get_ride_stats('STAMINA', 'LIQUID', 2.0, 1.0)".asExpression()
|
||||
private set
|
||||
|
||||
var staminaDecreaseExpr: Expression? = null
|
||||
var staminaDecreaseExpr = "q.get_ride_stats('STAMINA', 'LIQUID', 5.0, 1.0)".asExpression()
|
||||
private set
|
||||
|
||||
var rotationSpeedModifierExpr: Expression? = null
|
||||
var rotationspeedModifierExpr = "q.get_ride_stats('SKILL', 'LIQUID', 1.5, 0.5)".asExpression()
|
||||
private set
|
||||
|
||||
var jumpStrengthExpr: Expression? = null
|
||||
var jumpStrengthExpr = "q.get_ride_stats('JUMP', 'LIQUID', 2.5, 1.0)".asExpression()
|
||||
private set
|
||||
|
||||
var speedExpr: Expression? = null
|
||||
var speedExpr = "q.get_ride_stats('SPEED', 'LIQUID', 2.0, 0.5)".asExpression()
|
||||
private set
|
||||
|
||||
var accelerationExpr: Expression? = null
|
||||
var accelerationExpr = "q.get_ride_stats('ACCELERATION', 'LIQUID', 0.5, 0.05)".asExpression()
|
||||
private set
|
||||
|
||||
var sprintSpeedModifier: Expression? = null
|
||||
var sprintSpeedModifier = "1.5".asExpression()
|
||||
private set
|
||||
|
||||
var sprintFovModifier: Expression? = null
|
||||
|
||||
var surfaceLevelOffset: Expression? = null
|
||||
var sprintFovModifier = "1.2".asExpression()
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeResourceLocation(key)
|
||||
buffer.writeRidingStats(stats)
|
||||
rideSounds.encode(buffer)
|
||||
buffer.writeNullableExpression(terminalVelocity)
|
||||
buffer.writeNullableExpression(rotatePokemonHead)
|
||||
buffer.writeNullableExpression(staminaIncreaseExpr)
|
||||
buffer.writeNullableExpression(staminaDecreaseExpr)
|
||||
buffer.writeNullableExpression(rotationSpeedModifierExpr)
|
||||
buffer.writeNullableExpression(jumpStrengthExpr)
|
||||
buffer.writeNullableExpression(speedExpr)
|
||||
buffer.writeNullableExpression(accelerationExpr)
|
||||
buffer.writeNullableExpression(sprintSpeedModifier)
|
||||
buffer.writeNullableExpression(sprintFovModifier)
|
||||
buffer.writeNullableExpression(surfaceLevelOffset)
|
||||
buffer.writeExpression(terminalVelocity)
|
||||
}
|
||||
|
||||
override fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
stats.putAll(buffer.readRidingStats())
|
||||
rideSounds = RideSoundSettingsList.decode(buffer)
|
||||
terminalVelocity = buffer.readNullableExpression()
|
||||
rotatePokemonHead = buffer.readNullableExpression()
|
||||
staminaIncreaseExpr = buffer.readNullableExpression()
|
||||
staminaDecreaseExpr = buffer.readNullableExpression()
|
||||
rotationSpeedModifierExpr = buffer.readNullableExpression()
|
||||
jumpStrengthExpr = buffer.readNullableExpression()
|
||||
speedExpr = buffer.readNullableExpression()
|
||||
accelerationExpr = buffer.readNullableExpression()
|
||||
sprintSpeedModifier = buffer.readNullableExpression()
|
||||
sprintFovModifier = buffer.readNullableExpression()
|
||||
surfaceLevelOffset = buffer.readNullableExpression()
|
||||
terminalVelocity = buffer.readExpression()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+8
-14
@@ -8,14 +8,10 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.riding.behaviour.types.liquid
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonRideSettings
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.OrientationControllable
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviour
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviourSettings
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviourState
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.Side
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.ridingState
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.*
|
||||
import com.cobblemon.mod.common.api.riding.posing.PoseOption
|
||||
import com.cobblemon.mod.common.api.riding.posing.PoseProvider
|
||||
import com.cobblemon.mod.common.api.riding.sound.RideSoundSettingsList
|
||||
@@ -25,7 +21,6 @@ import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.blockPositionsAsListRounded
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.readRidingStats
|
||||
import com.cobblemon.mod.common.util.writeNullable
|
||||
import com.cobblemon.mod.common.util.writeRidingStats
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
@@ -43,8 +38,6 @@ class BurstBehaviour : RidingBehaviour<BurstSettings, BurstState> {
|
||||
}
|
||||
|
||||
override val key = KEY
|
||||
val globalBurst: BurstSettings
|
||||
get() = CobblemonRideSettings.burst
|
||||
|
||||
override fun getRidingStyle(settings: BurstSettings, state: BurstState): RidingStyle {
|
||||
return RidingStyle.LIQUID
|
||||
@@ -74,7 +67,7 @@ class BurstBehaviour : RidingBehaviour<BurstSettings, BurstState> {
|
||||
vehicle: PokemonEntity,
|
||||
driver: Player
|
||||
): Float {
|
||||
if (state.dashing.get()) {
|
||||
if(state.dashing.get()) {
|
||||
state.ticks.set(state.ticks.get() + 1)
|
||||
if(state.ticks.get() >= DASH_TICKS) {
|
||||
state.dashing.set(false)
|
||||
@@ -84,7 +77,7 @@ class BurstBehaviour : RidingBehaviour<BurstSettings, BurstState> {
|
||||
}
|
||||
|
||||
state.dashing.set(true)
|
||||
return settings.dashSpeed ?: globalBurst.dashSpeed!!
|
||||
return settings.dashSpeed
|
||||
}
|
||||
|
||||
override fun rotation(
|
||||
@@ -246,21 +239,22 @@ class BurstSettings : RidingBehaviourSettings {
|
||||
override val key = BurstBehaviour.KEY
|
||||
override val stats = mutableMapOf<RidingStat, IntRange>()
|
||||
|
||||
var dashSpeed: Float? = null
|
||||
var dashSpeed = 1F
|
||||
private set
|
||||
|
||||
var rideSounds: RideSoundSettingsList = RideSoundSettingsList()
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeResourceLocation(key)
|
||||
buffer.writeRidingStats(stats)
|
||||
rideSounds.encode(buffer)
|
||||
buffer.writeNullable(dashSpeed) { buf, speed -> buf.writeFloat(speed) }
|
||||
buffer.writeFloat(dashSpeed)
|
||||
}
|
||||
|
||||
override fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
stats.putAll(buffer.readRidingStats())
|
||||
rideSounds = RideSoundSettingsList.decode(buffer)
|
||||
dashSpeed = buffer.readNullable { buf -> buf.readFloat() }
|
||||
dashSpeed = buffer.readFloat()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+61
-71
@@ -10,33 +10,21 @@ package com.cobblemon.mod.common.api.riding.behaviour.types.liquid
|
||||
|
||||
import com.bedrockk.molang.Expression
|
||||
import com.bedrockk.molang.runtime.MoLangMath.lerp
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.CobblemonRideSettings
|
||||
import com.cobblemon.mod.common.OrientationControllable
|
||||
import com.cobblemon.mod.common.api.orientation.OrientationController
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviour
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviourSettings
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.RidingBehaviourState
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.Side
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.ridingState
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.*
|
||||
import com.cobblemon.mod.common.api.riding.posing.PoseOption
|
||||
import com.cobblemon.mod.common.api.riding.posing.PoseProvider
|
||||
import com.cobblemon.mod.common.api.riding.sound.RideSoundSettingsList
|
||||
import com.cobblemon.mod.common.api.riding.stats.RidingStat
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import com.cobblemon.mod.common.util.math.geometry.toDegrees
|
||||
import com.cobblemon.mod.common.util.math.geometry.toRadians
|
||||
import com.cobblemon.mod.common.util.readNullableExpression
|
||||
import com.cobblemon.mod.common.util.readRidingStats
|
||||
import com.cobblemon.mod.common.util.resolveBoolean
|
||||
import com.cobblemon.mod.common.util.resolveDouble
|
||||
import com.cobblemon.mod.common.util.toVec3d
|
||||
import com.cobblemon.mod.common.util.writeNullableExpression
|
||||
import com.cobblemon.mod.common.util.writeRidingStats
|
||||
import kotlin.math.*
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
@@ -47,6 +35,18 @@ import net.minecraft.world.entity.LivingEntity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraft.world.phys.Vec2
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import net.minecraft.world.phys.shapes.Shapes
|
||||
import org.joml.Vector3f
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.asin
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.hypot
|
||||
import kotlin.math.max
|
||||
import kotlin.math.min
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.sign
|
||||
import kotlin.math.sin
|
||||
import kotlin.math.sqrt
|
||||
|
||||
class DolphinBehaviour : RidingBehaviour<DolphinSettings, DolphinState> {
|
||||
companion object {
|
||||
@@ -54,8 +54,6 @@ class DolphinBehaviour : RidingBehaviour<DolphinSettings, DolphinState> {
|
||||
}
|
||||
|
||||
override val key = KEY
|
||||
val globalDolphin: DolphinSettings
|
||||
get() = CobblemonRideSettings.dolphin
|
||||
|
||||
override fun getRidingStyle(settings: DolphinSettings, state: DolphinState): RidingStyle {
|
||||
return RidingStyle.LIQUID
|
||||
@@ -119,14 +117,10 @@ class DolphinBehaviour : RidingBehaviour<DolphinSettings, DolphinState> {
|
||||
) {
|
||||
val stam = state.stamina.get()
|
||||
|
||||
if (vehicle.runtime.resolveBoolean(settings.infiniteStamina ?: globalDolphin.infiniteStamina!!)) {
|
||||
return
|
||||
}
|
||||
|
||||
// Grab the boost time in seconds and convert to ticks. Then calculate the drain rate as inversely
|
||||
// proportional to the number of ticks of boost thus making a full boost take x ticks
|
||||
// in short: "Stamina drains slower at higher values and also replenishes slower"
|
||||
val boostTime = vehicle.runtime.resolveDouble(settings.staminaExpr ?: globalDolphin.staminaExpr!!) * 20.0f
|
||||
val boostTime = vehicle.runtime.resolveDouble(settings.staminaExpr) * 20.0f
|
||||
val stamDrainRate = (1.0f / boostTime).toFloat()
|
||||
|
||||
val newStam = if (state.boosting.get()) max(0.0f,stam - stamDrainRate)
|
||||
@@ -155,9 +149,9 @@ class DolphinBehaviour : RidingBehaviour<DolphinSettings, DolphinState> {
|
||||
val controller = (driver as OrientationControllable).orientationController
|
||||
|
||||
val runtime = vehicle.runtime
|
||||
val boostMod = if (state.boosting.get()) runtime.resolveDouble(settings.jumpExpr ?: globalDolphin.jumpExpr!!) else 1.0
|
||||
val topSpeed = (vehicle.runtime.resolveDouble(settings.speedExpr ?: globalDolphin.speedExpr!!) / 20.0) * boostMod
|
||||
val accel = (topSpeed / (vehicle.runtime.resolveDouble(settings.accelerationExpr ?: globalDolphin.accelerationExpr!!) * 20.0)) * boostMod
|
||||
val boostMod = if (state.boosting.get()) runtime.resolveDouble(settings.jumpExpr) else 1.0
|
||||
val topSpeed = (vehicle.runtime.resolveDouble(settings.speedExpr) / 20.0) * boostMod
|
||||
val accel = (topSpeed / (vehicle.runtime.resolveDouble(settings.accelerationExpr) * 20.0)) * boostMod
|
||||
|
||||
/*********************************************
|
||||
* Breaching logic
|
||||
@@ -195,8 +189,8 @@ class DolphinBehaviour : RidingBehaviour<DolphinSettings, DolphinState> {
|
||||
}
|
||||
|
||||
val currSpeed = state.speed.get()
|
||||
val strafeFactor = runtime.resolveDouble(settings.strafeFactor ?: globalDolphin.strafeFactor!!)
|
||||
val reverseDriveFactor = runtime.resolveDouble(settings.reverseDriveFactor ?: globalDolphin.reverseDriveFactor!!)
|
||||
val strafeFactor = runtime.resolveDouble(settings.strafeFactor)
|
||||
val reverseDriveFactor = runtime.resolveDouble(settings.reverseDriveFactor)
|
||||
val f = -driver.xxa * strafeFactor
|
||||
when {
|
||||
driver.zza > 0.0 -> state.speed.set(min(topSpeed, currSpeed + accel))
|
||||
@@ -231,8 +225,8 @@ class DolphinBehaviour : RidingBehaviour<DolphinSettings, DolphinState> {
|
||||
|
||||
val currSpeed = vehicle.deltaMovement.length()
|
||||
|
||||
val handling = vehicle.runtime.resolveDouble(settings.handlingExpr ?: globalDolphin.handlingExpr!!)
|
||||
val topSpeed = vehicle.runtime.resolveDouble(settings.speedExpr ?: globalDolphin.speedExpr!!) / 20.0
|
||||
val handling = vehicle.runtime.resolveDouble(settings.handlingExpr)
|
||||
val topSpeed = vehicle.runtime.resolveDouble(settings.speedExpr) / 20.0
|
||||
|
||||
val yawDeltaDeg = deltaTime * handling * sin(Math.toRadians(controller.roll.toDouble())).pow(2) * sin(Math.toRadians(controller.roll.toDouble())).sign
|
||||
val trueYawDelt = yawDeltaDeg * abs(cos(Math.toRadians(controller.pitch.toDouble()))) * sqrt(RidingBehaviour.scaleToRange(currSpeed, 0.0, topSpeed))
|
||||
@@ -259,7 +253,7 @@ class DolphinBehaviour : RidingBehaviour<DolphinSettings, DolphinState> {
|
||||
// Calculate correcting roll force.
|
||||
// Mult by cos(pitch) to ensure that it doesn't roll correct at when diving or climbing
|
||||
val currSpeed = vehicle.deltaMovement.length()
|
||||
val rollCorrectionTimer = vehicle.runtime.resolveDouble(settings.timeToRollCorrect ?: globalDolphin.timeToRollCorrect!!)
|
||||
val rollCorrectionTimer = vehicle.runtime.resolveDouble(settings.timeToRollCorrect)
|
||||
val maxRollCorrectionRate = if (!(vehicle.isInWater || vehicle.isUnderWater)) 15.0f
|
||||
else 10.0f * (cos(controller.pitch.toRadians())).pow(2) * ((state.noInputTime.get() - rollCorrectionTimer) * 2).coerceIn(0.0, 1.0).toFloat()
|
||||
val maxRollForce = maxRollCorrectionRate / 40.0
|
||||
@@ -380,8 +374,8 @@ class DolphinBehaviour : RidingBehaviour<DolphinSettings, DolphinState> {
|
||||
controller.rotateRoll(controller.roll * -1.0f)
|
||||
|
||||
val boostingHandleDebuff = if (state.boosting.get()) 0.2 else 1.0
|
||||
val handling = vehicle.runtime.resolveDouble(settings.handlingExpr ?: globalDolphin.handlingExpr!!) * boostingHandleDebuff
|
||||
val mouseInputMult = vehicle.runtime.resolveDouble(settings.mouseInputMult ?: globalDolphin.mouseInputMult!!)
|
||||
val handling = vehicle.runtime.resolveDouble(settings.handlingExpr) * boostingHandleDebuff
|
||||
val mouseInputMult = vehicle.runtime.resolveDouble(settings.mouseInputMult)
|
||||
|
||||
//Smooth out mouse input.
|
||||
val smoothingSpeed = 4.0
|
||||
@@ -424,9 +418,9 @@ class DolphinBehaviour : RidingBehaviour<DolphinSettings, DolphinState> {
|
||||
): Vec3 {
|
||||
if (driver !is OrientationControllable) return Vec3.ZERO
|
||||
val controller = (driver as OrientationControllable).orientationController
|
||||
val topSpeed = vehicle.runtime.resolveDouble(settings.speedExpr ?: globalDolphin.speedExpr!!) / 20.0
|
||||
val topSpeed = vehicle.runtime.resolveDouble(settings.speedExpr) / 20.0
|
||||
val boostingHandleDebuff = if (state.boosting.get()) 0.2 else 1.0
|
||||
val mouseInputMult = vehicle.runtime.resolveDouble(settings.mouseInputMult ?: globalDolphin.mouseInputMult!!) * boostingHandleDebuff
|
||||
val mouseInputMult = vehicle.runtime.resolveDouble(settings.mouseInputMult) * boostingHandleDebuff
|
||||
|
||||
//Smooth out mouse input.
|
||||
val smoothingSpeed = 4.0
|
||||
@@ -445,7 +439,7 @@ class DolphinBehaviour : RidingBehaviour<DolphinSettings, DolphinState> {
|
||||
// - Reduce pitch substantially when rolled and in a steep yaw. This prevents the player from ignoring a slow handling stat
|
||||
// - Do not pitch at all when at or below hover speed
|
||||
// - pitch faster at higher speeds
|
||||
val p = 1.0 - vehicle.runtime.resolveDouble(settings.horizontalPitchExpr ?: globalDolphin.horizontalPitchExpr!!)
|
||||
val p = 1.0 - vehicle.runtime.resolveDouble(settings.horizontalPitchExpr)
|
||||
val localPitch = yInput * (1 - abs(sin(controller.roll.toRadians())) * p * hypot(controller.forwardVector.x.toDouble(), controller.forwardVector.z.toDouble()).toFloat())
|
||||
// localPitch *= if (currSpeed > hoverSpeed) RidingBehaviour.scaleToRange(currSpeed, hoverSpeed, topSpeed)
|
||||
// else 0.0
|
||||
@@ -566,66 +560,62 @@ class DolphinSettings : RidingBehaviourSettings {
|
||||
override val key = DolphinBehaviour.KEY
|
||||
override val stats = mutableMapOf<RidingStat, IntRange>()
|
||||
|
||||
var infiniteStamina: Expression? = null
|
||||
var canJump = "true".asExpression()
|
||||
private set
|
||||
|
||||
var canJump: Expression? = null
|
||||
var reverseDriveFactor = "0.25".asExpression()
|
||||
private set
|
||||
|
||||
var reverseDriveFactor: Expression? = null
|
||||
var strafeFactor = "0.2".asExpression()
|
||||
private set
|
||||
|
||||
var strafeFactor: Expression? = null
|
||||
private set
|
||||
|
||||
var timeToRollCorrect: Expression? = null
|
||||
var timeToRollCorrect: Expression = "0.5".asExpression()
|
||||
private set
|
||||
|
||||
// Boost influence when boosting
|
||||
var jumpExpr: Expression? = null
|
||||
var jumpExpr: Expression = "q.get_ride_stats('JUMP', 'LIQUID', 2.2, 1.2)".asExpression()
|
||||
// Yaw rate in degrees per second
|
||||
var handlingExpr: Expression? = null
|
||||
var horizontalPitchExpr: Expression? = null
|
||||
var mouseInputMult: Expression? = null
|
||||
var handlingExpr: Expression = "q.get_ride_stats('SKILL', 'LIQUID', 100.0, 45.0)".asExpression()
|
||||
var horizontalPitchExpr: Expression = "q.get_ride_stats('SKILL', 'LIQUID', 0.3, 0.2)".asExpression()
|
||||
var mouseInputMult: Expression = "q.get_ride_stats('SKILL', 'LIQUID', 1.2, 0.8)".asExpression()
|
||||
// Top speed in Bl/s
|
||||
var speedExpr: Expression? = null
|
||||
var speedExpr: Expression = "q.get_ride_stats('SPEED', 'LIQUID', 15.0, 5.0)".asExpression()
|
||||
// Seconds to get to top speed
|
||||
var accelerationExpr: Expression? = null
|
||||
var accelerationExpr: Expression = "q.get_ride_stats('ACCELERATION', 'LIQUID', 2.0, 5.0)".asExpression()
|
||||
// Seconds of boost
|
||||
var staminaExpr: Expression? = null
|
||||
var staminaExpr: Expression = "q.get_ride_stats('STAMINA', 'LIQUID', 7.0, 3.0)".asExpression()
|
||||
|
||||
var rideSounds: RideSoundSettingsList = RideSoundSettingsList()
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeResourceLocation(key)
|
||||
buffer.writeRidingStats(stats)
|
||||
rideSounds.encode(buffer)
|
||||
buffer.writeNullableExpression(infiniteStamina)
|
||||
buffer.writeNullableExpression(canJump)
|
||||
buffer.writeNullableExpression(reverseDriveFactor)
|
||||
buffer.writeNullableExpression(strafeFactor)
|
||||
buffer.writeNullableExpression(jumpExpr)
|
||||
buffer.writeNullableExpression(handlingExpr)
|
||||
buffer.writeNullableExpression(horizontalPitchExpr)
|
||||
buffer.writeNullableExpression(mouseInputMult)
|
||||
buffer.writeNullableExpression(speedExpr)
|
||||
buffer.writeNullableExpression(accelerationExpr)
|
||||
buffer.writeNullableExpression(staminaExpr)
|
||||
buffer.writeExpression(canJump)
|
||||
buffer.writeExpression(reverseDriveFactor)
|
||||
buffer.writeExpression(strafeFactor)
|
||||
buffer.writeExpression(jumpExpr)
|
||||
buffer.writeExpression(handlingExpr)
|
||||
buffer.writeExpression(horizontalPitchExpr)
|
||||
buffer.writeExpression(mouseInputMult)
|
||||
buffer.writeExpression(speedExpr)
|
||||
buffer.writeExpression(accelerationExpr)
|
||||
buffer.writeExpression(staminaExpr)
|
||||
}
|
||||
|
||||
override fun decode(buffer: RegistryFriendlyByteBuf) {
|
||||
stats.putAll(buffer.readRidingStats())
|
||||
rideSounds = RideSoundSettingsList.decode(buffer)
|
||||
infiniteStamina = buffer.readNullableExpression()
|
||||
canJump = buffer.readNullableExpression()
|
||||
reverseDriveFactor = buffer.readNullableExpression()
|
||||
strafeFactor = buffer.readNullableExpression()
|
||||
jumpExpr = buffer.readNullableExpression()
|
||||
handlingExpr = buffer.readNullableExpression()
|
||||
horizontalPitchExpr = buffer.readNullableExpression()
|
||||
mouseInputMult = buffer.readNullableExpression()
|
||||
speedExpr = buffer.readNullableExpression()
|
||||
accelerationExpr = buffer.readNullableExpression()
|
||||
staminaExpr = buffer.readNullableExpression()
|
||||
canJump = buffer.readExpression()
|
||||
reverseDriveFactor = buffer.readExpression()
|
||||
strafeFactor = buffer.readExpression()
|
||||
jumpExpr = buffer.readExpression()
|
||||
handlingExpr = buffer.readExpression()
|
||||
horizontalPitchExpr = buffer.readExpression()
|
||||
mouseInputMult = buffer.readExpression()
|
||||
speedExpr = buffer.readExpression()
|
||||
accelerationExpr = buffer.readExpression()
|
||||
staminaExpr = buffer.readExpression()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,11 +21,11 @@ import net.minecraft.network.chat.Component
|
||||
enum class RidingStat(
|
||||
val flavour: Flavour
|
||||
) {
|
||||
SPEED(Flavour.SWEET),
|
||||
ACCELERATION(Flavour.SPICY),
|
||||
SKILL(Flavour.DRY),
|
||||
SPEED(Flavour.SWEET),
|
||||
STAMINA(Flavour.SOUR),
|
||||
JUMP(Flavour.BITTER);
|
||||
JUMP(Flavour.BITTER),
|
||||
STAMINA(Flavour.SOUR);
|
||||
|
||||
companion object {
|
||||
fun getByName(name: String) = RidingStat.entries.firstOrNull { it.name.equals(name, ignoreCase = true) }
|
||||
|
||||
@@ -34,7 +34,7 @@ object CobblemonSpawnPools {
|
||||
SpawnablePositionTypePrecalculation,
|
||||
BucketPrecalculation,
|
||||
BiomePrecalculation
|
||||
), reloadable = true
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+70
-1
@@ -24,12 +24,14 @@ import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.PokeSnackBlockParticlesPacket
|
||||
import com.cobblemon.mod.common.util.math.pow
|
||||
import com.cobblemon.mod.common.util.toBlockPos
|
||||
import com.cobblemon.mod.common.util.toVec3d
|
||||
import kotlin.math.ceil
|
||||
import kotlin.math.sqrt
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Direction
|
||||
import net.minecraft.core.Holder
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.entity.ai.village.poi.PoiManager
|
||||
import net.minecraft.world.entity.ai.village.poi.PoiType
|
||||
import net.minecraft.world.level.block.Blocks
|
||||
@@ -112,6 +114,73 @@ object LurePokeSnackDetector : SpawningInfluenceDetector {
|
||||
}
|
||||
}
|
||||
|
||||
fun attemptSafeMove2(level: ServerLevel, startPos: BlockPos, entity: PokemonEntity, ) {
|
||||
val inWater = entity.isInWater
|
||||
|
||||
// Random offset in a cardinal direction (north, south, east, west)
|
||||
val randomDirection = listOf(Direction.NORTH, Direction.SOUTH, Direction.EAST, Direction.WEST).random()
|
||||
val initialOffsetPos = startPos.relative(randomDirection)
|
||||
|
||||
// Variables to track the best (closest) safe position
|
||||
var safePos: BlockPos? = null
|
||||
var bestDistanceSq = Double.MAX_VALUE
|
||||
|
||||
val maxRadius = 10
|
||||
|
||||
// Search within a sphere around the initial offset position
|
||||
for (dx in -maxRadius..maxRadius) {
|
||||
for (dy in -maxRadius..maxRadius) {
|
||||
for (dz in -maxRadius..maxRadius) {
|
||||
val candidatePos = initialOffsetPos.offset(dx, dy, dz)
|
||||
val distanceSq = startPos.distSqr(candidatePos)
|
||||
|
||||
// Check if within sphere radius
|
||||
if (dx*dx + dy*dy + dz*dz <= maxRadius*maxRadius) {
|
||||
// Check collision at candidate position
|
||||
val currentBox = entity.boundingBox.move(
|
||||
candidatePos.x - entity.x,
|
||||
candidatePos.y - entity.y,
|
||||
candidatePos.z - entity.z
|
||||
)
|
||||
|
||||
if (level.noCollision(entity, currentBox)) {
|
||||
val blockBelowPos = candidatePos.below()
|
||||
val blockState = level.getBlockState(blockBelowPos)
|
||||
|
||||
val isWater = blockState.block == Blocks.WATER
|
||||
if (inWater) {
|
||||
if (isWater) {
|
||||
if (distanceSq < bestDistanceSq) {
|
||||
bestDistanceSq = distanceSq
|
||||
safePos = candidatePos
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!blockState.isAir) {
|
||||
if (distanceSq < bestDistanceSq) {
|
||||
bestDistanceSq = distanceSq
|
||||
safePos = candidatePos
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (safePos != null) {
|
||||
entity.moveTo(safePos.toVec3d())
|
||||
PokeSnackBlockParticlesPacket(startPos, safePos).sendToPlayersAround(
|
||||
startPos.x.toDouble(),
|
||||
startPos.y.toDouble(),
|
||||
startPos.z.toDouble(),
|
||||
64.0,
|
||||
level.dimension()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun attemptSafeMove(level: ServerLevel, startPos: BlockPos, entity: PokemonEntity) {
|
||||
val inWater = entity.isInWater
|
||||
val maxDistance = 10 // maximum search radius
|
||||
@@ -186,4 +255,4 @@ object LurePokeSnackDetector : SpawningInfluenceDetector {
|
||||
}
|
||||
|
||||
override fun detectFromBlock(level: ServerLevel, pos: BlockPos, blockState: BlockState) = emptyList<SpawningZoneInfluence>()
|
||||
}
|
||||
}
|
||||
@@ -161,10 +161,6 @@ open class PlayerPartyStore(
|
||||
if (pokemon.interactionCooldowns.any()) {
|
||||
pokemon.tickInteractionCooldown()
|
||||
}
|
||||
|
||||
if (pokemon.entity?.passengers?.isNotEmpty() != true) {
|
||||
pokemon.rideStamina += 0.1F // Recover all stamina in 10 seconds, as long as no one's on it
|
||||
}
|
||||
}
|
||||
// Friendship
|
||||
// ToDo expand this down the line just a very basic implementation for the first releases
|
||||
|
||||
@@ -181,7 +181,7 @@ object ShowdownInterpreter {
|
||||
while (iterator.hasNext()) {
|
||||
val message = iterator.next()
|
||||
val id = message.id.replace("|", "")
|
||||
val instruction = updateInstructionParser[id]?.invoke(battle, instructionSet, message, iterator) ?: UnknownInstruction(message)
|
||||
val instruction: InterpreterInstruction = updateInstructionParser[id]?.invoke(battle, instructionSet, message, iterator) ?: UnknownInstruction(message)
|
||||
instructionSet.instructions.add(instruction)
|
||||
}
|
||||
}
|
||||
|
||||
+92
-11
@@ -15,6 +15,9 @@ import com.cobblemon.mod.common.CobblemonMemories
|
||||
import com.cobblemon.mod.common.api.battles.interpreter.BattleMessage
|
||||
import com.cobblemon.mod.common.api.battles.interpreter.Effect
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.api.battles.model.actor.EntityBackedBattleActor
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents
|
||||
import com.cobblemon.mod.common.api.events.battles.BattleFledEvent
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.addBattleMessageFunctions
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.addStandardFunctions
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMostSpecificMoLangValue
|
||||
@@ -22,19 +25,24 @@ import com.cobblemon.mod.common.api.moves.Moves
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import com.cobblemon.mod.common.api.moves.animations.TargetsProvider
|
||||
import com.cobblemon.mod.common.api.moves.animations.UsersProvider
|
||||
import com.cobblemon.mod.common.api.text.yellow
|
||||
import com.cobblemon.mod.common.battles.ShowdownInterpreter
|
||||
import com.cobblemon.mod.common.battles.actor.PlayerBattleActor
|
||||
import com.cobblemon.mod.common.battles.dispatch.CauserInstruction
|
||||
import com.cobblemon.mod.common.battles.dispatch.GO
|
||||
import com.cobblemon.mod.common.battles.dispatch.InstructionSet
|
||||
import com.cobblemon.mod.common.battles.dispatch.InterpreterInstruction
|
||||
import com.cobblemon.mod.common.battles.dispatch.UntilDispatch
|
||||
import com.cobblemon.mod.common.battles.pokemon.BattlePokemon
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.pokemon.evolution.progress.UseMoveEvolutionProgress
|
||||
import com.cobblemon.mod.common.util.asArrayValue
|
||||
import com.cobblemon.mod.common.util.battleLang
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.server.level.ServerLevel
|
||||
import net.minecraft.sounds.SoundEvents
|
||||
import java.util.concurrent.CompletableFuture
|
||||
import net.minecraft.world.entity.LivingEntity
|
||||
import java.lang.Math.*
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
/**
|
||||
* Format: |move|POKEMON|MOVE|TARGET
|
||||
@@ -72,17 +80,27 @@ class MoveInstruction(
|
||||
val pokemonName = userPokemon.getName()
|
||||
ShowdownInterpreter.lastCauser[battle.battleId] = message
|
||||
// For Spread targets the message data only gives the pnx strings. So we can't know what pokemon are actually targeted until the previous messages have been interpreted
|
||||
val spreadTargetPokemon = spreadTargets.map { battle.activePokemon.firstOrNull() { poke -> poke.getPNX() == it }?.battlePokemon }
|
||||
val spreadTargetPokemon =
|
||||
spreadTargets.map { battle.activePokemon.firstOrNull() { poke -> poke.getPNX() == it }?.battlePokemon }
|
||||
|
||||
val targetPokemonEntity = targetPokemon?.entity
|
||||
if (targetPokemonEntity != null) {
|
||||
userPokemon.entity?.brain?.setMemory(CobblemonMemories.TARGETED_BATTLE_POKEMON, targetPokemonEntity.uuid)
|
||||
userPokemon.entity?.brain?.setMemory(
|
||||
CobblemonMemories.TARGETED_BATTLE_POKEMON,
|
||||
targetPokemonEntity.uuid
|
||||
)
|
||||
}
|
||||
|
||||
userPokemon.effectedPokemon.let { pokemon ->
|
||||
if (UseMoveEvolutionProgress.supports(pokemon, move)) {
|
||||
val progress = pokemon.evolutionProxy.current().progressFirstOrCreate({ it is UseMoveEvolutionProgress && it.currentProgress().move == move }) { UseMoveEvolutionProgress() }
|
||||
progress.updateProgress(UseMoveEvolutionProgress.Progress(move, progress.currentProgress().amount + 1))
|
||||
val progress = pokemon.evolutionProxy.current()
|
||||
.progressFirstOrCreate({ it is UseMoveEvolutionProgress && it.currentProgress().move == move }) { UseMoveEvolutionProgress() }
|
||||
progress.updateProgress(
|
||||
UseMoveEvolutionProgress.Progress(
|
||||
move,
|
||||
progress.currentProgress().amount + 1
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,7 +122,7 @@ class MoveInstruction(
|
||||
|
||||
val providers = mutableListOf<Any>(battle)
|
||||
userPokemon.effectedPokemon.entity?.let { entity ->
|
||||
runtime.environment.query.addFunction("user") { entity.asMostSpecificMoLangValue()}
|
||||
runtime.environment.query.addFunction("user") { entity.asMostSpecificMoLangValue() }
|
||||
UsersProvider(entity)
|
||||
}?.let(providers::add)
|
||||
|
||||
@@ -128,6 +146,24 @@ class MoveInstruction(
|
||||
level = battle.players.firstOrNull()?.level()
|
||||
)
|
||||
|
||||
if (isWildTeleport(battle)) {
|
||||
var teleportSuccess = false
|
||||
val teleportingEntity = userPokemon.originalPokemon.entity
|
||||
if (teleportingEntity != null) {
|
||||
teleportSuccess = tryTeleport(battle.players.firstOrNull()?.level() as ServerLevel, teleportingEntity, 10, 30, 32)
|
||||
}
|
||||
|
||||
if (teleportSuccess){
|
||||
battle.ended = true
|
||||
battle.dispatchWaiting(1.0F) {
|
||||
battle.actors.filterIsInstance<EntityBackedBattleActor<*>>().mapNotNull { it.entity }
|
||||
.forEach { it.sendSystemMessage(battleLang("wild_flee", pokemonName).yellow()) }
|
||||
battle.end()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
val subsequentInstructions = instructionSet.findInstructionsCausedBy(this)
|
||||
val missedTargets = subsequentInstructions.filterIsInstance<MissInstruction>().mapNotNull { it.target }
|
||||
val hitCountInstruction = subsequentInstructions.filterIsInstance<HitCountInstruction>().firstOrNull()
|
||||
@@ -141,7 +177,8 @@ class MoveInstruction(
|
||||
}
|
||||
}
|
||||
|
||||
val hurtTargets = subsequentInstructions.filterIsInstance<DamageInstruction>().mapNotNull { it.expectedTarget }
|
||||
val hurtTargets =
|
||||
subsequentInstructions.filterIsInstance<DamageInstruction>().mapNotNull { it.expectedTarget }
|
||||
runtime.environment.query.addFunction("hurt") { params ->
|
||||
if (params.params.size == 0) {
|
||||
return@addFunction DoubleValue(hurtTargets.isNotEmpty())
|
||||
@@ -164,8 +201,52 @@ class MoveInstruction(
|
||||
return@dispatch UntilDispatch { "effects" !in holds }.andThen {
|
||||
val userPokemonId = userPokemon.entity?.uuid ?: return@andThen
|
||||
val targets = hurtTargets.mapNotNull { it.entity }
|
||||
userPokemonId.let { id -> targets.forEach { it.brain.setMemory(CobblemonMemories.TARGETED_BATTLE_POKEMON, id) } }
|
||||
userPokemonId.let { id ->
|
||||
targets.forEach {
|
||||
it.brain.setMemory(
|
||||
CobblemonMemories.TARGETED_BATTLE_POKEMON,
|
||||
id
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun tryTeleport(
|
||||
level: ServerLevel,
|
||||
pokemon: PokemonEntity,
|
||||
minRadius: Int,
|
||||
maxRadius: Int,
|
||||
attempts: Int
|
||||
): Boolean {
|
||||
val origin = pokemon.blockPosition()
|
||||
val rng = level.random
|
||||
var success = false
|
||||
|
||||
for (i in 0 until attempts) {
|
||||
val dist = rng.nextInt(minRadius, maxRadius + 1)
|
||||
val angle = rng.nextDouble() * (PI * 2.0)
|
||||
val dx = (cos(angle) * dist)
|
||||
val dz = (sin(angle) * dist)
|
||||
val x = (origin.x + dx)
|
||||
val yOffsetMax = rng.nextInt(5, 15)
|
||||
val z = (origin.z + dz)
|
||||
val yOffsets = (0..yOffsetMax).flatMap { listOf(it, -it) }.distinct()
|
||||
|
||||
//iterate over possible y distance, tries least vertical movement first
|
||||
for (yOffset in yOffsets){
|
||||
success = pokemon.randomTeleport(x, pokemon.position().y + yOffset, z, false)
|
||||
if (success) {
|
||||
level.playSoundServer(origin.toVec3d(), SoundEvents.PLAYER_TELEPORT)
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun isWildTeleport(battle: PokemonBattle) : Boolean {
|
||||
return move.name == "teleport" && message.battlePokemon(0, battle)?.originalPokemon?.isWild() ?: false
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,6 @@ package com.cobblemon.mod.common.block.entity
|
||||
import com.cobblemon.mod.common.CobblemonBlockEntities
|
||||
import com.cobblemon.mod.common.CobblemonRecipeTypes
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.cooking.Seasonings
|
||||
import com.cobblemon.mod.common.api.cooking.getColourMixFromSeasonings
|
||||
import com.cobblemon.mod.common.block.campfirepot.CampfireBlock
|
||||
import com.cobblemon.mod.common.item.components.PotComponent
|
||||
@@ -478,10 +477,9 @@ class CampfireBlockEntity(pos: BlockPos, state: BlockState) : BaseContainerBlock
|
||||
}
|
||||
|
||||
override fun canPlaceItemThroughFace(index: Int, itemStack: ItemStack, direction: Direction?): Boolean {
|
||||
return if(direction == Direction.UP && Seasonings.isSeasoning(itemStack)){
|
||||
SEASONING_SLOTS.contains(index)
|
||||
} else {
|
||||
CRAFTING_GRID_SLOTS.contains(index)
|
||||
return when (direction) {
|
||||
Direction.UP -> SEASONING_SLOTS.contains(index)
|
||||
else -> CRAFTING_GRID_SLOTS.contains(index)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,15 +29,7 @@ import com.cobblemon.mod.common.client.gui.cookingpot.CookingPotScreen
|
||||
import com.cobblemon.mod.common.client.particle.BedrockParticleOptionsRepository
|
||||
import com.cobblemon.mod.common.client.render.ClientPlayerIcon
|
||||
import com.cobblemon.mod.common.client.render.DeferredRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.BerryBlockRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.CampfireBlockEntityRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.DisplayCaseRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.FossilAnalyzerRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.GildedChestBlockRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.HealingMachineRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.LecternBlockEntityRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.PokeSnackBlockEntityRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.RestorationTankRenderer
|
||||
import com.cobblemon.mod.common.client.render.block.*
|
||||
import com.cobblemon.mod.common.client.render.boat.CobblemonBoatRenderer
|
||||
import com.cobblemon.mod.common.client.render.color.AprijuiceItemColorProvider
|
||||
import com.cobblemon.mod.common.client.render.color.PokeBaitItemColorProvider
|
||||
@@ -50,9 +42,7 @@ import com.cobblemon.mod.common.client.render.item.CobblemonBuiltinItemRendererR
|
||||
import com.cobblemon.mod.common.client.render.item.PokemonItemRenderer
|
||||
import com.cobblemon.mod.common.client.render.layer.PokemonOnShoulderRenderer
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.bedrock.animation.BedrockAnimationRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.BerryModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.MiscModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.VaryingModelRepository
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.*
|
||||
import com.cobblemon.mod.common.client.render.npc.NPCRenderer
|
||||
import com.cobblemon.mod.common.client.render.pokeball.PokeBallRenderer
|
||||
import com.cobblemon.mod.common.client.render.pokemon.PokemonRenderer
|
||||
@@ -60,25 +50,18 @@ import com.cobblemon.mod.common.client.requests.ClientPlayerActionRequests
|
||||
import com.cobblemon.mod.common.client.sound.BattleMusicController
|
||||
import com.cobblemon.mod.common.client.sound.EntitySoundTracker
|
||||
import com.cobblemon.mod.common.client.storage.ClientStorageManager
|
||||
import com.cobblemon.mod.common.client.tooltips.AprijuiceTooltipGenerator
|
||||
import com.cobblemon.mod.common.client.tooltips.CobblemonTooltipGenerator
|
||||
import com.cobblemon.mod.common.client.tooltips.FishingBaitTooltipGenerator
|
||||
import com.cobblemon.mod.common.client.tooltips.FishingRodTooltipGenerator
|
||||
import com.cobblemon.mod.common.client.tooltips.PokePuffTooltipGenerator
|
||||
import com.cobblemon.mod.common.client.tooltips.RecipeSeasoningAbsorbtionTooltipGenerator
|
||||
import com.cobblemon.mod.common.client.tooltips.SeasoningTooltipGenerator
|
||||
import com.cobblemon.mod.common.client.tooltips.TooltipManager
|
||||
import com.cobblemon.mod.common.client.tooltips.*
|
||||
import com.cobblemon.mod.common.client.trade.ClientTrade
|
||||
import com.cobblemon.mod.common.debug.RidingDebugRenderer
|
||||
import com.cobblemon.mod.common.data.CobblemonDataProvider
|
||||
import com.cobblemon.mod.common.entity.boat.CobblemonBoatType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.item.food.SinisterTeaItem
|
||||
import com.cobblemon.mod.common.platform.events.PlatformEvents
|
||||
import com.cobblemon.mod.common.pokedex.scanner.PokedexUsageContext
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.isLookingAt
|
||||
import io.github.flemmli97.debugutils.api.RegisterDebugRenderers
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.color.block.BlockColor
|
||||
import net.minecraft.client.color.item.ItemColor
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.screens.MenuScreens
|
||||
import net.minecraft.client.gui.screens.Screen
|
||||
@@ -121,7 +104,7 @@ object CobblemonClient {
|
||||
teamData = ClientPlayerTeamData()
|
||||
clientPokedexData = ClientPokedexManager(mutableMapOf())
|
||||
storage.onLogin()
|
||||
// CobblemonDataProvider.canReload = false
|
||||
CobblemonDataProvider.canReload = false
|
||||
}
|
||||
|
||||
fun onLogout() {
|
||||
@@ -130,7 +113,7 @@ object CobblemonClient {
|
||||
battleOverlay.onLogout()
|
||||
ClientTaskTracker.clear()
|
||||
checkedStarterScreen = false
|
||||
// CobblemonDataProvider.canReload = true
|
||||
CobblemonDataProvider.canReload = true
|
||||
DeferredRenderer.clearAll()
|
||||
ClientPlayerIcon.clear()
|
||||
}
|
||||
@@ -196,11 +179,6 @@ object CobblemonClient {
|
||||
}
|
||||
ClientPlayerIcon.onTick()
|
||||
}
|
||||
|
||||
val debugId = cobblemonResource("riding")
|
||||
RegisterDebugRenderers.registerCustomDebugRenderer(debugId, RidingDebugRenderer)
|
||||
RegisterDebugRenderers.registerServerToggle(debugId)
|
||||
RegisterDebugRenderers.registerClientHandler(debugId) { RidingDebugRenderer.clientHandler(it) }
|
||||
}
|
||||
|
||||
private fun registerTooltipManagers() {
|
||||
@@ -443,4 +421,5 @@ object CobblemonClient {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,71 +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
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.client.persisted.ClientPersistedData
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import net.minecraft.client.CameraType
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.entity.Entity
|
||||
|
||||
/**
|
||||
* The purpose here is to keep track of the last camera type that was used for each riding behaviour or just
|
||||
* the last overall, then change the camera type where necessary when mounting/dismounting or switching
|
||||
* between different riding behaviours. This is dependent on a config option, but the general idea is we
|
||||
* want the camera to be whatever the player feels most comfy with without them having to fiddle with it
|
||||
* more than once.
|
||||
*/
|
||||
object MountedCameraTypeHandler {
|
||||
var unmountedCameraType: CameraType = CameraType.FIRST_PERSON
|
||||
|
||||
fun handleMount(passenger: Entity, vehicle: PokemonEntity) {
|
||||
val mc = Minecraft.getInstance()
|
||||
val key = vehicle.ridingController?.context?.settings?.key
|
||||
if (passenger != mc.player || key == null) {
|
||||
return
|
||||
}
|
||||
unmountedCameraType = mc.options.cameraType
|
||||
val data = ClientPersistedData.ridingPerspectives
|
||||
if (Cobblemon.config.rememberRidingCamera) {
|
||||
val lastCameraTypeForKey = data.perspectives[key]
|
||||
if (lastCameraTypeForKey != null) {
|
||||
mc.options.cameraType = lastCameraTypeForKey
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun handleDismount(passenger: Entity, vehicle: PokemonEntity) {
|
||||
val mc = Minecraft.getInstance()
|
||||
val key = vehicle.ridingController?.context?.settings?.key
|
||||
if (passenger != mc.player || key == null) {
|
||||
return
|
||||
}
|
||||
val currentCameraType = mc.options.cameraType
|
||||
if (currentCameraType != unmountedCameraType) {
|
||||
mc.options.cameraType = unmountedCameraType
|
||||
}
|
||||
val data = ClientPersistedData.ridingPerspectives
|
||||
data.updatePerspective(key, currentCameraType)
|
||||
}
|
||||
|
||||
fun handleTransition(fromKey: ResourceLocation, toKey: ResourceLocation) {
|
||||
val mc = Minecraft.getInstance()
|
||||
val currentCameraType = mc.options.cameraType
|
||||
val data = ClientPersistedData.ridingPerspectives
|
||||
data.updatePerspective(fromKey, currentCameraType)
|
||||
if (Cobblemon.config.rememberRidingCamera) {
|
||||
val lastCameraTypeForKey = data.perspectives[toKey]
|
||||
if (lastCameraTypeForKey != null) {
|
||||
mc.options.cameraType = lastCameraTypeForKey
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -135,11 +135,7 @@ class RideControlsOverlay : Gui(Minecraft.getInstance()) {
|
||||
// Configure what controls to show for each behaviour
|
||||
when (currentBehaviourKey) {
|
||||
BirdBehaviour.KEY -> {}
|
||||
BoatBehaviour.KEY -> {
|
||||
showVerticalMouse = false
|
||||
showHorizontalMouse = false
|
||||
showSneakKey = false
|
||||
}
|
||||
BoatBehaviour.KEY -> {}
|
||||
BurstBehaviour.KEY -> {}
|
||||
DolphinBehaviour.KEY -> {}
|
||||
GliderBehaviour.KEY -> {}
|
||||
|
||||
-2
@@ -12,9 +12,7 @@ import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.config.CobblemonConfig
|
||||
import com.cobblemon.mod.common.util.asTranslated
|
||||
import com.cobblemon.mod.common.util.ifServer
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import com.cobblemon.mod.common.util.runOnServer
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.components.Button
|
||||
import net.minecraft.client.gui.components.EditBox
|
||||
|
||||
@@ -82,6 +82,9 @@ class PokedexGUI private constructor(
|
||||
private val arrowUpIcon = cobblemonResource("textures/gui/pokedex/arrow_up.png")
|
||||
private val arrowDownIcon = cobblemonResource("textures/gui/pokedex/arrow_down.png")
|
||||
|
||||
private val tooltipEdge = cobblemonResource("textures/gui/pokedex/tooltip_edge.png")
|
||||
private val tooltipBackground = cobblemonResource("textures/gui/pokedex/tooltip_background.png")
|
||||
|
||||
private val tabSelectArrow = cobblemonResource("textures/gui/pokedex/select_arrow.png")
|
||||
private val tabIcons = arrayOf(
|
||||
cobblemonResource("textures/gui/pokedex/tab_info.png"),
|
||||
@@ -322,15 +325,17 @@ class PokedexGUI private constructor(
|
||||
|
||||
// Search type tooltip
|
||||
if (searchByTypeButton.isButtonHovered(mouseX, mouseY)) {
|
||||
matrices.pushPose()
|
||||
matrices.translate(0.0, 0.0, 1000.0)
|
||||
val searchTypeText = lang("ui.pokedex.search.search_by", lang("ui.pokedex.search.type.${selectedSearchByType.name.lowercase()}")).bold()
|
||||
renderTooltip(
|
||||
context,
|
||||
searchTypeText,
|
||||
mouseX,
|
||||
mouseY,
|
||||
delta,
|
||||
-14
|
||||
)
|
||||
val searchTypeTextWidth = Minecraft.getInstance().font.width(searchTypeText.font(CobblemonResources.DEFAULT_LARGE))
|
||||
val tooltipWidth = searchTypeTextWidth + 6
|
||||
|
||||
blitk(matrixStack = matrices, texture = tooltipEdge, x = mouseX - (tooltipWidth / 2) - 1, y = mouseY - 16, width = 1, height = 11)
|
||||
blitk(matrixStack = matrices, texture = tooltipBackground, x = mouseX - (tooltipWidth / 2), y = mouseY - 16, width = tooltipWidth, height = 11)
|
||||
blitk(matrixStack = matrices, texture = tooltipEdge, x = mouseX + (tooltipWidth / 2), y = mouseY - 16, width = 1, height = 11)
|
||||
drawScaledText(context = context, font = CobblemonResources.DEFAULT_LARGE, text = searchTypeText, x = mouseX, y = mouseY - 15, shadow = true, centered = true)
|
||||
matrices.popPose()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -476,8 +481,6 @@ class PokedexGUI private constructor(
|
||||
|
||||
fun displaytabInfoElement(tabIndex: Int, update: Boolean = true) {
|
||||
val showActiveTab = selectedEntry?.let { selectedForm in CobblemonClient.clientPokedexData.getCaughtForms(it) } == true
|
||||
var statSubIndex = 0
|
||||
|
||||
if (tabButtons.isNotEmpty() && tabButtons.size > tabIndex) {
|
||||
tabButtons.forEachIndexed { index, tab -> tab.isWidgetActive = showActiveTab && index == tabIndex
|
||||
}
|
||||
@@ -488,14 +491,6 @@ class PokedexGUI private constructor(
|
||||
removeWidget((tabInfoElement as AbilitiesWidget).rightButton)
|
||||
}
|
||||
|
||||
if (tabInfoIndex == TAB_STATS && tabInfoElement is StatsWidget) {
|
||||
statSubIndex = (tabInfoElement as StatsWidget).selectedStatTypeIndex
|
||||
removeWidget((tabInfoElement as StatsWidget).leftButton)
|
||||
removeWidget((tabInfoElement as StatsWidget).rightButton)
|
||||
removeWidget((tabInfoElement as StatsWidget).leftSubButton)
|
||||
removeWidget((tabInfoElement as StatsWidget).rightSubButton)
|
||||
}
|
||||
|
||||
tabInfoIndex = tabIndex
|
||||
if (::tabInfoElement.isInitialized) removeWidget(tabInfoElement)
|
||||
|
||||
@@ -513,9 +508,7 @@ class PokedexGUI private constructor(
|
||||
tabInfoElement = SizeWidget(x + 180, y + 135)
|
||||
}
|
||||
TAB_STATS -> {
|
||||
tabInfoElement = StatsWidget(x + 180, y + 135).also {
|
||||
it.selectedStatTypeIndex = statSubIndex
|
||||
}
|
||||
tabInfoElement = StatsWidget(x + 180, y + 135)
|
||||
}
|
||||
TAB_DROPS -> {
|
||||
tabInfoElement = DropsScrollingWidget(x + 189, y + 135)
|
||||
@@ -562,17 +555,6 @@ class PokedexGUI private constructor(
|
||||
}
|
||||
TAB_STATS -> {
|
||||
(tabInfoElement as StatsWidget).baseStats = form.baseStats
|
||||
(tabInfoElement as StatsWidget).rideProperties = form.riding
|
||||
|
||||
form.riding.behaviours?.let {
|
||||
addRenderableWidget((tabInfoElement as StatsWidget).leftButton)
|
||||
addRenderableWidget((tabInfoElement as StatsWidget).rightButton)
|
||||
|
||||
if (it.size > 1) {
|
||||
addRenderableWidget((tabInfoElement as StatsWidget).leftSubButton)
|
||||
addRenderableWidget((tabInfoElement as StatsWidget).rightSubButton)
|
||||
}
|
||||
}
|
||||
}
|
||||
TAB_DROPS -> {
|
||||
(tabInfoElement as DropsScrollingWidget).dropTable = form.drops
|
||||
|
||||
@@ -1,50 +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.pokedex
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.text.font
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
|
||||
private val tooltipEdge = cobblemonResource("textures/gui/pokedex/tooltip_edge.png")
|
||||
private val tooltipBackground = cobblemonResource("textures/gui/pokedex/tooltip_background.png")
|
||||
|
||||
fun renderTooltip(context: GuiGraphics, text: MutableComponent, posX: Int, posY: Int, delta: Float, offsetY: Int = 0) {
|
||||
val poseStack = context.pose()
|
||||
val textWidth = Minecraft.getInstance().font.width(text.font(CobblemonResources.DEFAULT_LARGE))
|
||||
val tooltipWidth = textWidth + 6
|
||||
val tooltipHeight = 11
|
||||
val tooltipTop = posY + offsetY
|
||||
|
||||
poseStack.pushPose()
|
||||
poseStack.translate(0.0, 0.0, 1000.0)
|
||||
Minecraft.getInstance().let {
|
||||
it.mainRenderTarget.bindWrite(false)
|
||||
context.enableScissor(
|
||||
posX - (tooltipWidth / 2),
|
||||
tooltipTop + 1,
|
||||
(posX - (tooltipWidth / 2)) + tooltipWidth,
|
||||
tooltipTop + 10
|
||||
)
|
||||
it.gameRenderer.processBlurEffect(delta)
|
||||
context.disableScissor()
|
||||
it.mainRenderTarget.bindWrite(true)
|
||||
}
|
||||
|
||||
blitk(matrixStack = poseStack, texture = tooltipEdge, x = posX - (tooltipWidth / 2) - 1, y = tooltipTop, width = 1, height = tooltipHeight)
|
||||
blitk(matrixStack = poseStack, texture = tooltipBackground, x = posX - (tooltipWidth / 2), y = tooltipTop, width = tooltipWidth, height = tooltipHeight)
|
||||
blitk(matrixStack = poseStack, texture = tooltipEdge, x = posX + (tooltipWidth / 2), y = tooltipTop, width = 1, height = tooltipHeight)
|
||||
drawScaledText(context = context, font = CobblemonResources.DEFAULT_LARGE, text = text, x = posX, y = tooltipTop + 1, shadow = true, centered = true)
|
||||
poseStack.popPose()
|
||||
}
|
||||
@@ -31,7 +31,6 @@ class ScaledButton(
|
||||
): Button(buttonX.toInt(), buttonY.toInt(), buttonWidth.toInt(), buttonHeight.toInt(), "".text(), clickAction, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
|
||||
var isWidgetActive = false
|
||||
var isVisible = true
|
||||
|
||||
override fun mouseDragged(d: Double, e: Double, i: Int, f: Double, g: Double) = false
|
||||
override fun defaultButtonNarrationText(builder: NarrationElementOutput) {
|
||||
@@ -39,7 +38,8 @@ class ScaledButton(
|
||||
|
||||
override fun renderWidget(context: GuiGraphics, pMouseX: Int, pMouseY: Int, pPartialTicks: Float) {
|
||||
val matrices = context.pose()
|
||||
if (isVisible && resource != null) {
|
||||
|
||||
if (resource != null) {
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = resource,
|
||||
@@ -55,14 +55,14 @@ class ScaledButton(
|
||||
}
|
||||
|
||||
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
||||
if (isVisible && active && isButtonHovered(mouseX, mouseY)) {
|
||||
if (active && isButtonHovered(mouseX, mouseY)) {
|
||||
super.mouseClicked(mouseX, mouseY, button)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun playDownSound(soundManager: SoundManager) {
|
||||
if (isVisible && active && !this.silent) {
|
||||
if (active && !this.silent) {
|
||||
soundManager.play(SimpleSoundInstance.forUI(CobblemonSounds.POKEDEX_CLICK_SHORT, 1.0F))
|
||||
}
|
||||
}
|
||||
@@ -71,4 +71,4 @@ class ScaledButton(
|
||||
return mouseX.toFloat() in (buttonX..(buttonX + (buttonWidth.toFloat() * scale)))
|
||||
&& mouseY.toFloat() in (buttonY..(buttonY + (buttonHeight.toFloat() * scale)))
|
||||
}
|
||||
}
|
||||
}
|
||||
+5
-4
@@ -48,11 +48,12 @@ class AbilitiesWidget(x: Int, y: Int): InfoTextScrollWidget(pX = x, pY = y) {
|
||||
init { setAbility() }
|
||||
|
||||
private fun switchAbility(nextIndex: Boolean) {
|
||||
val size = abilitiesList.size
|
||||
selectedAbilitiesIndex = if (nextIndex) {
|
||||
(selectedAbilitiesIndex + 1) % size
|
||||
if (nextIndex) {
|
||||
if (selectedAbilitiesIndex < abilitiesList.lastIndex) selectedAbilitiesIndex++
|
||||
else selectedAbilitiesIndex = 0
|
||||
} else {
|
||||
(selectedAbilitiesIndex - 1 + size) % size
|
||||
if (selectedAbilitiesIndex > 0) selectedAbilitiesIndex--
|
||||
else selectedAbilitiesIndex = abilitiesList.lastIndex
|
||||
}
|
||||
setAbility()
|
||||
}
|
||||
|
||||
+10
-9
@@ -33,7 +33,6 @@ import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.PORTRAIT_
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.PORTRAIT_POKE_BALL_WIDTH
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.SCALE
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.ScaledButton
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.renderTooltip
|
||||
import com.cobblemon.mod.common.client.gui.summary.widgets.SoundlessWidget
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.client.render.drawScaledTextJustifiedRight
|
||||
@@ -95,6 +94,9 @@ class PokemonInfoWidget(val pX: Int, val pY: Int, val updateForm: (PokedexForm)
|
||||
private val buttonGenderFemale = cobblemonResource("textures/gui/pokedex/button_female.png")
|
||||
private val buttonNone = cobblemonResource("textures/gui/pokedex/button_none.png")
|
||||
private val buttonShiny = cobblemonResource("textures/gui/pokedex/button_shiny.png")
|
||||
|
||||
private val tooltipEdge = cobblemonResource("textures/gui/pokedex/tooltip_edge.png")
|
||||
private val tooltipBackground = cobblemonResource("textures/gui/pokedex/tooltip_background.png")
|
||||
}
|
||||
|
||||
var currentEntry : PokedexEntry? = null
|
||||
@@ -438,14 +440,13 @@ class PokemonInfoWidget(val pX: Int, val pY: Int, val updateForm: (PokedexForm)
|
||||
// Tooltip
|
||||
if (it.isVisible() && it.getWidget().isButtonHovered(mouseX, mouseY)) {
|
||||
val variationText = it.variation.displayName.asTranslated().bold()
|
||||
renderTooltip(
|
||||
context,
|
||||
variationText,
|
||||
mouseX,
|
||||
mouseY,
|
||||
delta,
|
||||
10
|
||||
)
|
||||
val variationTextWidth = Minecraft.getInstance().font.width(variationText.font(CobblemonResources.DEFAULT_LARGE))
|
||||
val tooltipWidth = variationTextWidth + 6
|
||||
|
||||
blitk(matrixStack = matrices, texture = tooltipEdge, x = mouseX - (tooltipWidth / 2) - 1, y = mouseY + 8, width = 1, height = 11)
|
||||
blitk(matrixStack = matrices, texture = tooltipBackground, x = mouseX - (tooltipWidth / 2), y = mouseY + 8, width = tooltipWidth, height = 11)
|
||||
blitk(matrixStack = matrices, texture = tooltipEdge, x = mouseX + (tooltipWidth / 2), y = mouseY + 8, width = 1, height = 11)
|
||||
drawScaledText(context = context, font = CobblemonResources.DEFAULT_LARGE, text = variationText, x = mouseX, y = mouseY + 9, shadow = true, centered = true)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+17
-218
@@ -11,24 +11,18 @@ package com.cobblemon.mod.common.client.gui.pokedex.widgets
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stat
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||
import com.cobblemon.mod.common.api.riding.RidingProperties
|
||||
import com.cobblemon.mod.common.api.riding.stats.RidingStat
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.HALF_OVERLAY_WIDTH
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.POKEMON_DESCRIPTION_HEIGHT
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.SCALE
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.ScaledButton
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.renderTooltip
|
||||
import com.cobblemon.mod.common.client.gui.summary.widgets.SoundlessWidget
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.client.render.drawScaledTextJustifiedRight
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.util.FastColor
|
||||
|
||||
class StatsWidget(val pX: Int, val pY: Int) : SoundlessWidget(
|
||||
pX,
|
||||
@@ -39,18 +33,6 @@ class StatsWidget(val pX: Int, val pY: Int) : SoundlessWidget(
|
||||
) {
|
||||
|
||||
companion object {
|
||||
const val STAT_TYPE_BASE = 0
|
||||
const val STAT_TYPE_RIDE = 1
|
||||
const val MAX_BAR_WIDTH = 75
|
||||
|
||||
private val statTypes = listOf(STAT_TYPE_BASE, STAT_TYPE_RIDE)
|
||||
|
||||
private val divider = cobblemonResource("textures/gui/pokedex/info_stat_divider.png")
|
||||
private val arrowLeft = cobblemonResource("textures/gui/pokedex/info_arrow_left.png")
|
||||
private val arrowRight = cobblemonResource("textures/gui/pokedex/info_arrow_right.png")
|
||||
private val subArrowLeft = cobblemonResource("textures/gui/pokedex/info_sub_arrow_left.png")
|
||||
private val subArrowRight = cobblemonResource("textures/gui/pokedex/info_sub_arrow_right.png")
|
||||
|
||||
private val statLabels = arrayOf(
|
||||
lang("ui.stats.hp"),
|
||||
lang("ui.stats.atk"),
|
||||
@@ -70,92 +52,13 @@ class StatsWidget(val pX: Int, val pY: Int) : SoundlessWidget(
|
||||
)
|
||||
}
|
||||
|
||||
val leftButton: ScaledButton = ScaledButton(
|
||||
pX + 2.5F,
|
||||
pY - 8F,
|
||||
7,
|
||||
10,
|
||||
arrowLeft,
|
||||
clickAction = { switchStatType(false) }
|
||||
)
|
||||
|
||||
val rightButton: ScaledButton = ScaledButton(
|
||||
pX + 133F,
|
||||
pY - 8F,
|
||||
7,
|
||||
10,
|
||||
arrowRight,
|
||||
clickAction = { switchStatType(true) }
|
||||
)
|
||||
|
||||
val leftSubButton: ScaledButton = ScaledButton(
|
||||
pX + 2.5F,
|
||||
pY + 18.5F,
|
||||
7,
|
||||
10,
|
||||
subArrowLeft,
|
||||
clickAction = { switchRideBehaviour(false) }
|
||||
)
|
||||
|
||||
val rightSubButton: ScaledButton = ScaledButton(
|
||||
pX + 133F,
|
||||
pY + 18.5F,
|
||||
7,
|
||||
10,
|
||||
subArrowRight,
|
||||
clickAction = { switchRideBehaviour(true) }
|
||||
)
|
||||
|
||||
var selectedRideBehavioursIndex: Int = 0
|
||||
|
||||
var selectedStatTypeIndex: Int = STAT_TYPE_BASE
|
||||
set(value) {
|
||||
field = value
|
||||
|
||||
val isRideStatVisible = value == STAT_TYPE_RIDE
|
||||
leftSubButton.visible = isRideStatVisible
|
||||
rightSubButton.visible = isRideStatVisible
|
||||
}
|
||||
|
||||
var baseStats: Map<Stat, Int>? = null
|
||||
var rideProperties: RidingProperties? = null
|
||||
|
||||
private fun switchStatType(nextIndex: Boolean) {
|
||||
val size = statTypes.size
|
||||
selectedStatTypeIndex = if (nextIndex) {
|
||||
(selectedStatTypeIndex + 1) % size
|
||||
} else {
|
||||
(selectedStatTypeIndex - 1 + size) % size
|
||||
}
|
||||
|
||||
val showSubArrowButtons = selectedStatTypeIndex == STAT_TYPE_RIDE
|
||||
leftSubButton.visible = showSubArrowButtons
|
||||
rightSubButton.visible = showSubArrowButtons
|
||||
}
|
||||
|
||||
private fun switchRideBehaviour(nextIndex: Boolean) {
|
||||
val size = rideProperties?.behaviours?.size ?: 0
|
||||
selectedRideBehavioursIndex = if (nextIndex) {
|
||||
(selectedRideBehavioursIndex + 1) % size
|
||||
} else {
|
||||
(selectedRideBehavioursIndex - 1 + size) % size
|
||||
}
|
||||
}
|
||||
|
||||
override fun renderWidget(context: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
|
||||
when (selectedStatTypeIndex) {
|
||||
STAT_TYPE_BASE -> {
|
||||
renderBaseStats(context)
|
||||
}
|
||||
STAT_TYPE_RIDE -> {
|
||||
renderRideStats(context, mouseX, mouseY, delta)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun renderBaseStats(context: GuiGraphics) {
|
||||
if (baseStats == null) return
|
||||
|
||||
val matrices = context.pose()
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
font = CobblemonResources.DEFAULT_LARGE,
|
||||
@@ -165,9 +68,18 @@ class StatsWidget(val pX: Int, val pY: Int) : SoundlessWidget(
|
||||
shadow = true
|
||||
)
|
||||
|
||||
val matrices = context.pose()
|
||||
|
||||
blitk(matrixStack = matrices, texture = divider, x = pX + 51, y = pY + 4, height = 33.5, width = 1)
|
||||
// Divider
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = CobblemonResources.WHITE,
|
||||
x = pX + 50.5,
|
||||
y = pY + 4,
|
||||
height = 33.5,
|
||||
width = 1,
|
||||
red = 0.71F,
|
||||
green = 0.95F,
|
||||
blue = 0.95F
|
||||
)
|
||||
|
||||
for (i in statLabels.indices) {
|
||||
drawScaledText(
|
||||
@@ -195,10 +107,10 @@ class StatsWidget(val pX: Int, val pY: Int) : SoundlessWidget(
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = CobblemonResources.WHITE,
|
||||
x = pX + 55,
|
||||
x = pX + 54.5,
|
||||
y = pY + 4 + (6 * i),
|
||||
height = 3.5F,
|
||||
width = (statValue / 255F) * MAX_BAR_WIDTH,
|
||||
width = (statValue / 255F) * 77,
|
||||
red = red,
|
||||
green = green,
|
||||
blue = blue
|
||||
@@ -207,119 +119,6 @@ class StatsWidget(val pX: Int, val pY: Int) : SoundlessWidget(
|
||||
}
|
||||
}
|
||||
|
||||
private fun renderRideStats(context: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
|
||||
rideProperties?.behaviours?.let { behaviours ->
|
||||
val selectedBehaviour = behaviours.entries.toList()[selectedRideBehavioursIndex]
|
||||
val behaviourStats = selectedBehaviour.value.stats
|
||||
|
||||
val matrices = context.pose()
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
font = CobblemonResources.DEFAULT_LARGE,
|
||||
text = Component.translatable("cobblemon.ui.pokedex.info.stats_ride").bold(),
|
||||
x = pX + 9,
|
||||
y = pY - 10,
|
||||
shadow = true
|
||||
)
|
||||
|
||||
rideProperties?.seats?.size?.let { seats ->
|
||||
drawScaledTextJustifiedRight(
|
||||
context = context,
|
||||
font = CobblemonResources.DEFAULT_LARGE,
|
||||
text = Component.translatable("cobblemon.ui.pokedex.info.stats_ride.seats", seats).bold(),
|
||||
x = pX + 130,
|
||||
y = pY - 10,
|
||||
shadow = true
|
||||
)
|
||||
}
|
||||
|
||||
blitk(matrixStack = matrices, texture = divider, x = pX + 51, y = pY + 10, height = 27.5, width = 1)
|
||||
blitk(matrixStack = matrices, texture = divider, x = pX + 9, y = pY + 2, height = 6, width = 121)
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = lang("ui.ride_style.${selectedBehaviour.key.name.lowercase()}").bold(),
|
||||
x = pX + 69.5,
|
||||
y = pY + 3,
|
||||
colour = 0x3A96B6,
|
||||
scale = SCALE,
|
||||
centered = true
|
||||
)
|
||||
|
||||
RidingStat.entries.forEachIndexed { index, stat ->
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = lang("ui.stats.ride.${stat.name.lowercase()}").bold(),
|
||||
x = pX + 9,
|
||||
y = pY + 10 + (6 * index),
|
||||
colour = 0x606B6E,
|
||||
scale = SCALE
|
||||
)
|
||||
|
||||
behaviourStats[stat]?.let { range ->
|
||||
val startPosY = pY + 10 + (6F * index)
|
||||
|
||||
val red = FastColor.ARGB32.red(stat.flavour.colour) / 255F
|
||||
val green = FastColor.ARGB32.green(stat.flavour.colour) / 255F
|
||||
val blue = FastColor.ARGB32.blue(stat.flavour.colour) / 255F
|
||||
|
||||
val barStart = pX + 55F
|
||||
val baseStatWidth = (range.start / 100F) * MAX_BAR_WIDTH
|
||||
val boostedStatWidth = ((range.endInclusive / 100F) * MAX_BAR_WIDTH) - baseStatWidth
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = CobblemonResources.WHITE,
|
||||
x = barStart,
|
||||
y = startPosY,
|
||||
height = 3.5F,
|
||||
width = baseStatWidth,
|
||||
red = red,
|
||||
green = green,
|
||||
blue = blue
|
||||
)
|
||||
|
||||
val isBoostedStatHovered = mouseX.toFloat() in ((barStart + baseStatWidth)..(barStart + baseStatWidth + boostedStatWidth)) && mouseY.toFloat() in (startPosY..(startPosY + 3.5F))
|
||||
|
||||
drawScaledTextJustifiedRight(
|
||||
context = context,
|
||||
text = if (isBoostedStatHovered) range.endInclusive.toString().text().bold() else range.start.toString().text(),
|
||||
x = pX + 48,
|
||||
y = startPosY,
|
||||
colour = 0x3A96B6,
|
||||
scale = SCALE
|
||||
)
|
||||
|
||||
// Boostable range
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = CobblemonResources.WHITE,
|
||||
x = barStart + baseStatWidth,
|
||||
y = startPosY,
|
||||
height = 3.5F,
|
||||
width = boostedStatWidth,
|
||||
red = red,
|
||||
green = green,
|
||||
blue = blue,
|
||||
alpha = if (isBoostedStatHovered) 1F else 0.5F
|
||||
)
|
||||
|
||||
if (isBoostedStatHovered) renderTooltip(
|
||||
context,
|
||||
lang("ui.stats.ride.boost_maximum").bold(),
|
||||
mouseX,
|
||||
mouseY,
|
||||
delta,
|
||||
-16
|
||||
)
|
||||
}
|
||||
}
|
||||
} ?: run {
|
||||
// If ride properties null, reset index to base stats
|
||||
selectedStatTypeIndex = STAT_TYPE_BASE
|
||||
}
|
||||
}
|
||||
|
||||
private fun getStatValueRGB(value: Int): Triple<Float, Float, Float> {
|
||||
when {
|
||||
value >= 150 -> return Triple(0.647F, 0.929F, 0.647F)
|
||||
@@ -329,4 +128,4 @@ class StatsWidget(val pX: Int, val pY: Int) : SoundlessWidget(
|
||||
}
|
||||
return Triple(0.964F, 0.64F, 0.502F)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -53,7 +53,7 @@ class SummaryButton(
|
||||
override fun defaultButtonNarrationText(builder: NarrationElementOutput) {
|
||||
}
|
||||
|
||||
public override fun renderWidget(context: GuiGraphics, pMouseX: Int, pMouseY: Int, pPartialTicks: Float) {
|
||||
override fun renderWidget(context: GuiGraphics, pMouseX: Int, pMouseY: Int, pPartialTicks: Float) {
|
||||
if (!this.renderRequirement.invoke(this)) {
|
||||
return
|
||||
}
|
||||
|
||||
+58
-66
@@ -28,91 +28,83 @@ import net.minecraft.world.phys.Vec3
|
||||
* @author Hiroku
|
||||
* @since November 13th, 2023
|
||||
*/
|
||||
open class BarSummarySpeciesFeatureRenderer(
|
||||
class BarSummarySpeciesFeatureRenderer(
|
||||
override val name: String,
|
||||
val displayName: MutableComponent,
|
||||
val underlay: ResourceLocation,
|
||||
val overlay: ResourceLocation,
|
||||
val pokemon: Pokemon,
|
||||
val min: Int,
|
||||
val max: Int,
|
||||
val value: Int = 0,
|
||||
val colour: Vec3? = null
|
||||
val colour: Vec3,
|
||||
val underlay: ResourceLocation,
|
||||
val overlay: ResourceLocation,
|
||||
val pokemon: Pokemon
|
||||
) : SummarySpeciesFeatureRenderer<IntSpeciesFeature> {
|
||||
override fun render(guiGraphics: GuiGraphics, x: Float, y: Float, pokemon: Pokemon, feature: IntSpeciesFeature) {
|
||||
renderElement(guiGraphics, x, y, pokemon, feature.value)
|
||||
}
|
||||
|
||||
open fun renderElement(guiGraphics: GuiGraphics, x: Float, y: Float, pokemon: Pokemon, barValue: Int = value) {
|
||||
val barRatio = (barValue - min) / (max - min).toFloat()
|
||||
val barWidth = Mth.ceil(barRatio * 110)
|
||||
override fun render(GuiGraphics: GuiGraphics, x: Float, y: Float, pokemon: Pokemon, feature: IntSpeciesFeature) {
|
||||
val value = feature.value
|
||||
val barRatio = (value - min) / (max - min).toFloat()
|
||||
val barWidth = Mth.ceil(barRatio * 108)
|
||||
|
||||
blitk(
|
||||
matrixStack = guiGraphics.pose(),
|
||||
matrixStack = GuiGraphics.pose(),
|
||||
texture = underlay,
|
||||
x = x,
|
||||
y = y,
|
||||
height = 24,
|
||||
width = 116
|
||||
height = 28,
|
||||
width = 124
|
||||
)
|
||||
|
||||
renderBar(guiGraphics, x, y, barValue, barRatio, barWidth)
|
||||
val red = colour.x / 255F
|
||||
val green = colour.y / 255F
|
||||
val blue = colour.z / 255F
|
||||
|
||||
blitk(
|
||||
matrixStack = guiGraphics.pose(),
|
||||
texture = overlay,
|
||||
x = (x + 3) / StatWidget.SCALE,
|
||||
y = (y + 13) / StatWidget.SCALE,
|
||||
height = 20,
|
||||
width = 220,
|
||||
scale = StatWidget.SCALE
|
||||
)
|
||||
|
||||
// Label
|
||||
drawScaledText(
|
||||
context = guiGraphics,
|
||||
font = CobblemonResources.DEFAULT_LARGE,
|
||||
text = displayName.bold(),
|
||||
x = x + 58,
|
||||
y = y + 2.5,
|
||||
centered = true,
|
||||
shadow = true
|
||||
)
|
||||
|
||||
drawScaledText(
|
||||
context = guiGraphics,
|
||||
text = barValue.toString().text(),
|
||||
x = x + 9,
|
||||
y = y + 6,
|
||||
scale = StatWidget.SCALE,
|
||||
centered = true
|
||||
)
|
||||
|
||||
drawScaledText(
|
||||
context = guiGraphics,
|
||||
text = "${Mth.floor(barRatio * 100)}%".text(),
|
||||
x = x + 107,
|
||||
y = y + 6,
|
||||
scale = StatWidget.SCALE,
|
||||
centered = true
|
||||
)
|
||||
}
|
||||
|
||||
open fun renderBar(guiGraphics: GuiGraphics, x: Float, y: Float, barValue: Int, barRatio: Float, barWidth: Int) {
|
||||
val red = (colour?.x ?: 255.0) / 255.0
|
||||
val green = (colour?.y ?: 255.0) / 255.0
|
||||
val blue = (colour?.z ?: 255.0) / 255.0
|
||||
|
||||
blitk(
|
||||
matrixStack = guiGraphics.pose(),
|
||||
matrixStack = GuiGraphics.pose(),
|
||||
texture = CobblemonResources.WHITE,
|
||||
x = x + 3,
|
||||
y = y + 13,
|
||||
x = x + 8,
|
||||
y = y + 16,
|
||||
height = 10,
|
||||
width = barWidth,
|
||||
red = red,
|
||||
green = green,
|
||||
blue = blue
|
||||
)
|
||||
|
||||
blitk(
|
||||
matrixStack = GuiGraphics.pose(),
|
||||
texture = overlay,
|
||||
x = x / StatWidget.SCALE,
|
||||
y = (y + 16) / StatWidget.SCALE,
|
||||
height = 20,
|
||||
width = 248,
|
||||
scale = StatWidget.SCALE
|
||||
)
|
||||
|
||||
// Label
|
||||
drawScaledText(
|
||||
context = GuiGraphics,
|
||||
font = CobblemonResources.DEFAULT_LARGE,
|
||||
text = displayName.bold(),
|
||||
x = x + 62,
|
||||
y = y + 2.5,
|
||||
centered = true,
|
||||
shadow = true
|
||||
)
|
||||
|
||||
drawScaledText(
|
||||
context = GuiGraphics,
|
||||
text = value.toString().text(),
|
||||
x = x + 11,
|
||||
y = y + 6,
|
||||
scale = StatWidget.SCALE,
|
||||
centered = true
|
||||
)
|
||||
|
||||
drawScaledText(
|
||||
context = GuiGraphics,
|
||||
text = "${Mth.floor(barRatio * 100)}%".text(),
|
||||
x = x + 113,
|
||||
y = y + 6,
|
||||
scale = StatWidget.SCALE,
|
||||
centered = true
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -23,10 +23,10 @@ interface SummarySpeciesFeatureRenderer<T : SynchronizedSpeciesFeature> {
|
||||
/** The name of the feature (so we know where to look to find it in the [Pokemon]) */
|
||||
val name: String
|
||||
/** Draws it at a particular position. */
|
||||
fun render(guiGraphics: GuiGraphics, x: Float, y: Float, pokemon: Pokemon, feature: T)
|
||||
fun render(guiGraphics: GuiGraphics, x: Float, y: Float, pokemon: Pokemon): Boolean {
|
||||
fun render(GuiGraphics: GuiGraphics, x: Float, y: Float, pokemon: Pokemon, feature: T)
|
||||
fun render(GuiGraphics: GuiGraphics, x: Float, y: Float, pokemon: Pokemon): Boolean {
|
||||
val feature = pokemon.getFeature<T>(name) ?: return false
|
||||
render(guiGraphics, x, y, pokemon, feature)
|
||||
render(GuiGraphics, x, y, pokemon, feature)
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
+448
-402
@@ -14,16 +14,12 @@ import com.cobblemon.mod.common.api.pokemon.feature.SpeciesFeatures
|
||||
import com.cobblemon.mod.common.api.pokemon.feature.SynchronizedSpeciesFeatureProvider
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stat
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle
|
||||
import com.cobblemon.mod.common.api.riding.stats.RidingStat
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.api.text.italicise
|
||||
import com.cobblemon.mod.common.api.text.onHover
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.summary.SummaryButton
|
||||
import com.cobblemon.mod.common.client.gui.summary.featurerenderers.BarSummarySpeciesFeatureRenderer
|
||||
import com.cobblemon.mod.common.client.gui.summary.widgets.SoundlessWidget
|
||||
import com.cobblemon.mod.common.client.gui.summary.widgets.screens.stats.features.FriendshipFeatureRenderer
|
||||
import com.cobblemon.mod.common.client.gui.summary.widgets.screens.stats.features.FullnessFeatureRenderer
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
@@ -43,6 +39,8 @@ import net.minecraft.util.Mth.ceil
|
||||
import net.minecraft.util.Mth.floor
|
||||
import net.minecraft.world.phys.Vec2
|
||||
import org.joml.Vector3f
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.sin
|
||||
|
||||
class StatWidget(
|
||||
pX: Int, pY: Int,
|
||||
@@ -53,129 +51,63 @@ class StatWidget(
|
||||
companion object {
|
||||
// Stat tab options
|
||||
private const val STATS = "stats"
|
||||
private const val IV = "ivs"
|
||||
private const val EV = "evs"
|
||||
private const val RIDE = "ride"
|
||||
private const val IV = "iv"
|
||||
private const val EV = "ev"
|
||||
private const val OTHER = "other"
|
||||
|
||||
private const val OTHER_STAT_BARS_PER_PAGE = 4
|
||||
private const val STAT_TAB_WIDTH_6 = 22
|
||||
private const val STAT_TAB_WIDTH_5 = 24
|
||||
private const val MARKER_WIDTH = 8
|
||||
private val statOptions = listOf(STATS, IV, EV, OTHER)
|
||||
|
||||
private const val statTabWidth = 24
|
||||
private const val WIDTH = 134
|
||||
private const val HEIGHT = 148
|
||||
const val SCALE = 0.5F
|
||||
|
||||
private const val WHITE = 0x00FFFFFF
|
||||
private const val GREY = 0x008F8F8F
|
||||
private const val GREY = 0x00AAAAAA
|
||||
private const val BLUE = 0x00548BFB
|
||||
private const val RED = 0x00FB5454
|
||||
|
||||
private val statsBaseResource = cobblemonResource("textures/gui/summary/summary_stats_chart_base.png")
|
||||
private val statsChartResource = cobblemonResource("textures/gui/summary/summary_stats_chart.png")
|
||||
private val statsChartPentagonResource = cobblemonResource("textures/gui/summary/summary_stats_chart_pentagon.png")
|
||||
private val statsOtherBaseResource = cobblemonResource("textures/gui/summary/summary_stats_other_base.png")
|
||||
private val statsOtherSidebarsResource = cobblemonResource("textures/gui/summary/summary_stats_other_sidebars.png")
|
||||
private val statsOtherSidebarArrowLeft = cobblemonResource("textures/gui/summary/summary_stats_other_sidebar_arrow_left.png")
|
||||
private val statsOtherSidebarArrowRight = cobblemonResource("textures/gui/summary/summary_stats_other_sidebar_arrow_right.png")
|
||||
private val statsOtherBarTemplate = cobblemonResource("textures/gui/summary/summary_stats_other_bar.png")
|
||||
private val friendshipOverlayResource = cobblemonResource("textures/gui/summary/summary_stats_friendship_overlay.png")
|
||||
private val fullnessOverlayResource = cobblemonResource("textures/gui/summary/summary_stats_fullness_overlay.png")
|
||||
private val tabMarkerResource = cobblemonResource("textures/gui/summary/summary_stats_tab_marker.png")
|
||||
private val statIncreaseResource = cobblemonResource("textures/gui/summary/summary_stats_icon_increase.png")
|
||||
private val statDecreaseResource = cobblemonResource("textures/gui/summary/summary_stats_icon_decrease.png")
|
||||
|
||||
private val statLabels: Map<MutableComponent, Stats> = mapOf(
|
||||
lang("ui.stats.hp").bold() to Stats.HP,
|
||||
lang("ui.stats.atk").bold() to Stats.ATTACK,
|
||||
lang("ui.stats.def").bold() to Stats.DEFENCE,
|
||||
lang("ui.stats.speed").bold() to Stats.SPEED,
|
||||
lang("ui.stats.sp_def").bold() to Stats.SPECIAL_DEFENCE,
|
||||
lang("ui.stats.sp_atk").bold() to Stats.SPECIAL_ATTACK
|
||||
)
|
||||
private val statsLabel = lang("ui.stats")
|
||||
private val ivLabel = lang("ui.stats.ivs")
|
||||
private val evLabel = lang("ui.stats.evs")
|
||||
private val otherLabel = lang("ui.stats.other")
|
||||
|
||||
private val hexagonVerticesOffset = listOf(
|
||||
Pair(67.0, 10.5), // 12 o'clock
|
||||
Pair(122.0, 42.5), // 2 o'clock
|
||||
Pair(122.0, 93.5), // 4 o'clock
|
||||
Pair(67.0, 124.5), // 6 o'clock
|
||||
Pair(12.0, 93.5), // 8 o'clock
|
||||
Pair(12.0, 42.5) // 10 o'clock
|
||||
)
|
||||
|
||||
private val pentagonVerticesOffset = listOf(
|
||||
Pair(67.0, 10.5), // 12 o'clock
|
||||
Pair(123.0, 47.5), // 2 o'clock
|
||||
Pair(103.0, 112.5), // 5 o'clock
|
||||
Pair(31.0, 112.5), // 7 o'clock
|
||||
Pair(11.0, 47.5), // 10 o'clock
|
||||
)
|
||||
private val hpLabel = lang("ui.stats.hp")
|
||||
private val spAtkLabel = lang("ui.stats.sp_atk")
|
||||
private val atkLabel = lang("ui.stats.atk")
|
||||
private val spDefLabel = lang("ui.stats.sp_def")
|
||||
private val defLabel = lang("ui.stats.def")
|
||||
private val speedLabel = lang("ui.stats.speed")
|
||||
}
|
||||
|
||||
private val statOptions = if (pokemon.form.riding.behaviours != null) listOf(STATS, IV, EV, RIDE, OTHER) else listOf(STATS, IV, EV, OTHER)
|
||||
|
||||
private var _statTabIndex: Int = tabIndex
|
||||
var statTabIndex: Int
|
||||
get() = _statTabIndex.coerceIn(0, statOptions.size - 1)
|
||||
set(value) {
|
||||
_statTabIndex = value.coerceIn(0, statOptions.size - 1)
|
||||
}
|
||||
|
||||
private var _rideBehaviourIndex: Int = 0
|
||||
var rideBehaviourIndex: Int
|
||||
get() = _rideBehaviourIndex.coerceIn(0, (pokemon.form.riding.behaviours?.size ?: 1) - 1)
|
||||
set(value) {
|
||||
_rideBehaviourIndex = value.coerceIn(0, (pokemon.form.riding.behaviours?.size ?: 1) - 1)
|
||||
}
|
||||
|
||||
val universalFeatures = listOf(
|
||||
FriendshipFeatureRenderer(pokemon),
|
||||
FullnessFeatureRenderer(pokemon)
|
||||
)
|
||||
var effectiveBattleIVs: Map<Stat, Int> = Stats.PERMANENT.associateWith { stat ->
|
||||
pokemon.ivs.getEffectiveBattleIV(stat)
|
||||
}
|
||||
|
||||
var statTabIndex = tabIndex
|
||||
val renderableFeatures = SpeciesFeatures
|
||||
.getFeaturesFor(pokemon.species)
|
||||
.filterIsInstance<SynchronizedSpeciesFeatureProvider<*>>()
|
||||
.mapNotNull { it.getRenderer(pokemon) }
|
||||
|
||||
var otherStatsPageIndex: Int = 0
|
||||
|
||||
var otherStatLeftButton: SummaryButton? = null
|
||||
var otherStatRightButton: SummaryButton? = null
|
||||
|
||||
init {
|
||||
if (renderableFeatures.size + universalFeatures.size > OTHER_STAT_BARS_PER_PAGE) {
|
||||
otherStatLeftButton = SummaryButton(
|
||||
x - 1F,
|
||||
y + 67F,
|
||||
14,
|
||||
14,
|
||||
resource = statsOtherSidebarArrowLeft,
|
||||
scale = SCALE,
|
||||
clickAction = { switchOtherStatsPage(false) }
|
||||
).also { addWidget(it) }
|
||||
|
||||
otherStatRightButton = SummaryButton(
|
||||
x + 128F,
|
||||
y + 67F,
|
||||
14,
|
||||
14,
|
||||
resource = statsOtherSidebarArrowRight,
|
||||
scale = SCALE,
|
||||
clickAction = { switchOtherStatsPage(true) }
|
||||
).also { addWidget(it) }
|
||||
}
|
||||
}
|
||||
|
||||
private fun switchOtherStatsPage(nextIndex: Boolean) {
|
||||
val pages = ceil((renderableFeatures.size + universalFeatures.size).toDouble() / OTHER_STAT_BARS_PER_PAGE.toDouble())
|
||||
otherStatsPageIndex = if (nextIndex) {
|
||||
(otherStatsPageIndex + 1) % pages
|
||||
} else {
|
||||
(otherStatsPageIndex - 1 + pages) % pages
|
||||
}
|
||||
}
|
||||
|
||||
private fun drawTriangle(colour: Vector3f, v1: Vec2, v2: Vec2, v3: Vec2, opacity: Float = 0.6F) {
|
||||
private fun drawTriangle(
|
||||
colour: Vector3f,
|
||||
v1: Vec2,
|
||||
v2: Vec2,
|
||||
v3: Vec2
|
||||
) {
|
||||
CobblemonResources.WHITE.let { RenderSystem.setShaderTexture(0, it) }
|
||||
RenderSystem.setShaderColor(colour.x, colour.y, colour.z, opacity)
|
||||
RenderSystem.setShaderColor(colour.x, colour.y, colour.z, 0.6F)
|
||||
val bufferBuilder = Tesselator.getInstance().begin(VertexFormat.Mode.TRIANGLES, DefaultVertexFormat.POSITION)
|
||||
bufferBuilder.addVertex(v1.x, v1.y, 10F)
|
||||
bufferBuilder.addVertex(v2.x, v2.y, 10F)
|
||||
@@ -184,325 +116,396 @@ class StatWidget(
|
||||
RenderSystem.setShaderColor(1F, 1F, 1F, 1F)
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a 5 or 6 sided polygon
|
||||
*
|
||||
* @param ratios list of ratios for how far each vertex is from the center, starting from top vertex going clockwise
|
||||
* @param colour the colour to render
|
||||
*/
|
||||
private fun drawStatPolygon(ratios: List<Float>, colour: Vector3f) {
|
||||
val sides = ratios.size
|
||||
if (sides !in 5 .. 6) return
|
||||
private fun drawStatHexagon(stats: Map<Stat, Int>, colour: Vector3f, maximum: Int) {
|
||||
val hexLeftX = x + 25.5
|
||||
val hexTopY = y + 22
|
||||
val hexAttackY = hexTopY + 24.5
|
||||
val hexDefenceY = hexAttackY + 47.0
|
||||
val hexBottomY = hexDefenceY + 24.5
|
||||
val hexRightX = x + 108.5
|
||||
val hexCenterX = (hexLeftX + hexRightX) / 2
|
||||
val hexCenterY = (hexTopY + hexBottomY) / 2
|
||||
val minTriangleSize = 8F
|
||||
val minXTriangleLen = sin(Math.toRadians(61.0)).toFloat() * minTriangleSize * 0.95F
|
||||
val minYTriangleLen = cos(Math.toRadians(60.0)).toFloat() * minTriangleSize
|
||||
|
||||
val topVertexY = y + 22F
|
||||
val centerX = x + 67F
|
||||
val centerY = topVertexY + if (sides > 5) 48F else 49F
|
||||
val triangleLongEdge = (hexCenterY - hexTopY - minTriangleSize).toFloat()
|
||||
val triangleMediumEdge = (triangleLongEdge * sin(Math.toRadians(61.0))).toFloat()
|
||||
val triangleShortEdge = (triangleLongEdge * cos(Math.toRadians(61.0))).toFloat()
|
||||
|
||||
val radius = centerY - topVertexY
|
||||
val hpRatio = (stats.getOrDefault(Stats.HP, 0).toFloat() / maximum).coerceIn(0F, 1F)
|
||||
val atkRatio = (stats.getOrDefault(Stats.ATTACK, 0).toFloat() / maximum).coerceIn(0F, 1F)
|
||||
val defRatio = (stats.getOrDefault(Stats.DEFENCE, 0).toFloat() / maximum).coerceIn(0F, 1F)
|
||||
val spAtkRatio = (stats.getOrDefault(Stats.SPECIAL_ATTACK, 0).toFloat() / maximum).coerceIn(0F, 1F)
|
||||
val spDefRatio = (stats.getOrDefault(Stats.SPECIAL_DEFENCE, 0).toFloat() / maximum).coerceIn(0F, 1F)
|
||||
val spdRatio = (stats.getOrDefault(Stats.SPEED, 0).toFloat() / maximum).coerceIn(0F, 1F)
|
||||
|
||||
val startAngleDeg = -90.0
|
||||
val angleStepDeg = 360.0 / sides
|
||||
val hpPoint = Vec2(
|
||||
hexCenterX.toFloat(),
|
||||
hexCenterY.toFloat() - minTriangleSize - hpRatio * triangleLongEdge
|
||||
)
|
||||
|
||||
// Generate the angles for each vertex
|
||||
val anglesDeg = List(sides) { i -> startAngleDeg + i * angleStepDeg }
|
||||
val anglesRad = anglesDeg.map { Math.toRadians(it) }
|
||||
val attackPoint = Vec2(
|
||||
hexCenterX.toFloat() + minXTriangleLen + atkRatio * triangleMediumEdge,
|
||||
hexCenterY.toFloat() - minYTriangleLen - atkRatio * triangleShortEdge
|
||||
)
|
||||
|
||||
// Calculate maximum points on the circle
|
||||
val maxPoints = anglesRad.map { angle ->
|
||||
Vec2(
|
||||
centerX + radius * Math.cos(angle).toFloat(),
|
||||
centerY + radius * Math.sin(angle).toFloat()
|
||||
)
|
||||
val defencePoint = Vec2(
|
||||
hexCenterX.toFloat() + minXTriangleLen + defRatio * triangleMediumEdge,
|
||||
hexCenterY.toFloat() + minYTriangleLen + defRatio * triangleShortEdge
|
||||
)
|
||||
|
||||
val specialAttackPoint = Vec2(
|
||||
hexCenterX.toFloat() - minXTriangleLen - spAtkRatio * triangleMediumEdge,
|
||||
hexCenterY.toFloat() - minYTriangleLen - spAtkRatio * triangleShortEdge
|
||||
)
|
||||
|
||||
val specialDefencePoint = Vec2(
|
||||
hexCenterX.toFloat() - minXTriangleLen - spDefRatio * triangleMediumEdge,
|
||||
hexCenterY.toFloat() + minYTriangleLen + spDefRatio * triangleShortEdge
|
||||
)
|
||||
|
||||
val speedPoint = Vec2(
|
||||
hexCenterX.toFloat(),
|
||||
hexCenterY.toFloat() + minTriangleSize + spdRatio * triangleLongEdge
|
||||
)
|
||||
|
||||
val centerPoint = Vec2(
|
||||
hexCenterX.toFloat(),
|
||||
hexCenterY.toFloat()
|
||||
)
|
||||
|
||||
// 1-o'clock
|
||||
drawTriangle(colour, hpPoint, centerPoint, attackPoint)
|
||||
// 3-o'clock
|
||||
drawTriangle(colour, attackPoint, centerPoint, defencePoint)
|
||||
// 5-o'clock
|
||||
drawTriangle(colour, defencePoint, centerPoint, speedPoint)
|
||||
// 7-o'clock
|
||||
drawTriangle(colour, speedPoint, centerPoint, specialDefencePoint)
|
||||
// 9-o'clock
|
||||
drawTriangle(colour, specialDefencePoint, centerPoint, specialAttackPoint)
|
||||
// 11-o'clock
|
||||
drawTriangle(colour, specialAttackPoint, centerPoint, hpPoint)
|
||||
}
|
||||
|
||||
private fun drawFriendship(moduleX: Int, moduleY: Int, matrices: PoseStack, context: GuiGraphics, friendship: Int) {
|
||||
val barRatio = friendship / 255F
|
||||
val barWidth = ceil(barRatio * 108)
|
||||
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = statsOtherBarTemplate,
|
||||
x = moduleX,
|
||||
y = moduleY,
|
||||
height = 28,
|
||||
width = 124
|
||||
)
|
||||
|
||||
val red = 1
|
||||
val green: Number = if (pokemon.friendship >= 160) 0.28 else 0.56
|
||||
val blue: Number = if (pokemon.friendship >= 160) 0.4 else 0.64
|
||||
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = CobblemonResources.WHITE,
|
||||
x = moduleX + 8,
|
||||
y = moduleY + 18,
|
||||
height = 8,
|
||||
width = barWidth,
|
||||
red = red,
|
||||
green = green,
|
||||
blue = blue
|
||||
)
|
||||
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = friendshipOverlayResource,
|
||||
x = moduleX / SCALE,
|
||||
y = (moduleY + 16) / SCALE,
|
||||
height = 20,
|
||||
width = 248,
|
||||
scale = SCALE
|
||||
)
|
||||
|
||||
// Label
|
||||
drawScaledText(
|
||||
context = context,
|
||||
font = CobblemonResources.DEFAULT_LARGE,
|
||||
text = lang("ui.stats.friendship").bold(),
|
||||
x = moduleX + 62,
|
||||
y = moduleY + 2.5,
|
||||
centered = true,
|
||||
shadow = true
|
||||
)
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = friendship.toString().text(),
|
||||
x = moduleX + 11,
|
||||
y = moduleY + 6,
|
||||
scale = SCALE,
|
||||
centered = true
|
||||
)
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = "${floor(barRatio * 100)}%".text(),
|
||||
x = moduleX + 113,
|
||||
y = moduleY + 6,
|
||||
scale = SCALE,
|
||||
centered = true
|
||||
)
|
||||
}
|
||||
|
||||
private fun drawFullness(moduleX: Int, moduleY: Int, matrices: PoseStack, context: GuiGraphics, pokemon: Pokemon) {
|
||||
val currentFullness = pokemon.currentFullness
|
||||
val maxFullness = pokemon.getMaxFullness()
|
||||
val barRatio = currentFullness.toFloat() / maxFullness.toFloat()
|
||||
val barWidth = ceil(barRatio * 108)
|
||||
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = statsOtherBarTemplate,
|
||||
x = moduleX,
|
||||
y = moduleY,
|
||||
height = 28,
|
||||
width = 124
|
||||
)
|
||||
|
||||
val (red, green, blue) = when {
|
||||
barRatio <= 0.33 -> Triple(0f, 1f, 0f) // Green (full green)
|
||||
barRatio <= 0.66 -> Triple(1f, 1f, 0f) // Yellow (red + green)
|
||||
else -> Triple(1f, 0f, 0f) // Red (full red)
|
||||
}
|
||||
|
||||
// Coerce values as 0.0 will prevent triangles from rendering
|
||||
val coercedRatios = ratios.map { it.coerceIn(5 / radius, 1F) }
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = CobblemonResources.WHITE,
|
||||
x = moduleX + 8,
|
||||
y = moduleY + 18,
|
||||
height = 8,
|
||||
width = barWidth,
|
||||
red = red,
|
||||
green = green,
|
||||
blue = blue
|
||||
)
|
||||
|
||||
// Interpolate vertices based on ratios
|
||||
val vertices = maxPoints.mapIndexed { index, maxPoint ->
|
||||
Vec2(
|
||||
centerX + (maxPoint.x - centerX) * coercedRatios[index],
|
||||
centerY + (maxPoint.y - centerY) * coercedRatios[index]
|
||||
)
|
||||
}
|
||||
// Draw the overlay
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = fullnessOverlayResource,
|
||||
x = moduleX / SCALE,
|
||||
y = (moduleY + 16) / SCALE,
|
||||
height = 20,
|
||||
width = 248,
|
||||
scale = SCALE
|
||||
)
|
||||
|
||||
val centerPoint = Vec2(centerX, centerY)
|
||||
drawScaledText(
|
||||
context = context,
|
||||
font = CobblemonResources.DEFAULT_LARGE,
|
||||
text = "Fullness".text().bold(),
|
||||
x = moduleX + 62,
|
||||
y = moduleY + 2.5,
|
||||
centered = true,
|
||||
shadow = true
|
||||
)
|
||||
|
||||
// Draw triangles between each vertex and the next clockwise starting from top vertex
|
||||
RenderSystem.disableDepthTest()
|
||||
for (i in vertices.indices) {
|
||||
val nextIndex = (i + 1) % vertices.size
|
||||
drawTriangle(colour, vertices[i], centerPoint, vertices[nextIndex])
|
||||
}
|
||||
RenderSystem.enableDepthTest()
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = currentFullness.toString().text(),
|
||||
x = moduleX + 11,
|
||||
y = moduleY + 6,
|
||||
scale = SCALE,
|
||||
centered = true
|
||||
)
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = "${floor(barRatio * 100)}%".text(),
|
||||
x = moduleX + 113,
|
||||
y = moduleY + 6,
|
||||
scale = SCALE,
|
||||
centered = true
|
||||
)
|
||||
}
|
||||
|
||||
override fun renderWidget(context: GuiGraphics, pMouseX: Int, pMouseY: Int, pPartialTicks: Float) {
|
||||
val renderOtherStats = statOptions.get(statTabIndex) == OTHER
|
||||
val renderPentagonStats = statOptions.get(statTabIndex) == RIDE
|
||||
val renderChart = statOptions.get(statTabIndex) != OTHER
|
||||
val matrices = context.pose()
|
||||
|
||||
// Background
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = if (renderOtherStats) statsOtherBaseResource else statsBaseResource,
|
||||
texture = if (renderChart) statsBaseResource else statsOtherBaseResource,
|
||||
x= x,
|
||||
y = y,
|
||||
width = width,
|
||||
height = height
|
||||
)
|
||||
|
||||
if (renderOtherStats) {
|
||||
val barOffsetY = 29
|
||||
val barPosX = x + 9F
|
||||
var drawY = y + 15F
|
||||
|
||||
val featuresList: MutableList<Any> = renderableFeatures.toMutableList()
|
||||
featuresList.addAll(0, universalFeatures)
|
||||
|
||||
val pageFeatures = featuresList.subList(
|
||||
otherStatsPageIndex * OTHER_STAT_BARS_PER_PAGE,
|
||||
minOf((otherStatsPageIndex * OTHER_STAT_BARS_PER_PAGE) + OTHER_STAT_BARS_PER_PAGE, featuresList.size)
|
||||
// Chart
|
||||
if (renderChart) {
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = statsChartResource,
|
||||
x= (x + 25.5) / SCALE,
|
||||
y = (y + 22) / SCALE,
|
||||
width = 166,
|
||||
height = 192,
|
||||
scale = SCALE
|
||||
)
|
||||
|
||||
for (feature in pageFeatures) {
|
||||
if (feature is BarSummarySpeciesFeatureRenderer) {
|
||||
val rendered = feature.render(
|
||||
guiGraphics = context,
|
||||
x = barPosX,
|
||||
y = drawY,
|
||||
pokemon = pokemon
|
||||
)
|
||||
if (rendered) drawY += barOffsetY
|
||||
}
|
||||
}
|
||||
if (featuresList.size > 4) {
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = statsOtherSidebarsResource,
|
||||
x= x,
|
||||
y = y + 13,
|
||||
width = 134,
|
||||
height = 115
|
||||
)
|
||||
otherStatLeftButton?.renderWidget(context, pMouseX, pMouseY, pPartialTicks)
|
||||
otherStatRightButton?.renderWidget(context, pMouseX, pMouseY, pPartialTicks)
|
||||
}
|
||||
} else {
|
||||
if (renderPentagonStats) {
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = statsChartPentagonResource,
|
||||
x= (x + 20.5) / SCALE,
|
||||
y = (y + 22) / SCALE,
|
||||
width = 186,
|
||||
height = 176,
|
||||
scale = SCALE
|
||||
)
|
||||
|
||||
pokemon.form.riding.behaviours?.let {
|
||||
val behaviours = it.entries.toList()
|
||||
val selectedBehaviour = behaviours[rideBehaviourIndex]
|
||||
|
||||
val pentagonColour = when (selectedBehaviour.key) {
|
||||
RidingStyle.AIR -> {
|
||||
if (behaviours.size > 1 && centerHovered(pMouseX, pMouseY))
|
||||
Vector3f(70F/255F, 235F/225F, 195F/255F)
|
||||
else Vector3f(40F/255F, 205F/255F, 165F/255F)
|
||||
}
|
||||
RidingStyle.LIQUID -> {
|
||||
if (behaviours.size > 1 && centerHovered(pMouseX, pMouseY))
|
||||
Vector3f(95F/255F, 165F/255F, 1F)
|
||||
else Vector3f(65F/255F, 135F/255F, 1F)
|
||||
}
|
||||
else -> {
|
||||
if (behaviours.size > 1 && centerHovered(pMouseX, pMouseY))
|
||||
Vector3f(1F, 195F/255F, 30F/255F)
|
||||
else Vector3f(1F, 165F/255F, 0F)
|
||||
}
|
||||
}
|
||||
|
||||
drawStatPolygon(
|
||||
ratios = RidingStat.entries.map { pokemon.getRideStat(selectedBehaviour.key, it) / 100F },
|
||||
colour = pentagonColour
|
||||
)
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
font = CobblemonResources.DEFAULT_LARGE,
|
||||
text = lang("ui.ride_style.${selectedBehaviour.key.name.lowercase()}").bold(),
|
||||
x = x + (WIDTH / 2),
|
||||
y = y + 66,
|
||||
shadow = true,
|
||||
centered = true
|
||||
)
|
||||
|
||||
// Stat Labels
|
||||
renderPolygonLabels(
|
||||
context = context,
|
||||
labels = RidingStat.entries.toList().map { stat ->
|
||||
if (statLabelsHovered(pentagonVerticesOffset, pMouseX, pMouseY))
|
||||
"${floor(pokemon.getRideStat(selectedBehaviour.key, stat))}/${selectedBehaviour.value.stats[stat]?.endInclusive}".text()
|
||||
else lang("ui.stats.ride.${stat.name.lowercase()}").bold()
|
||||
},
|
||||
verticesOffset = pentagonVerticesOffset
|
||||
)
|
||||
|
||||
// Stat Values
|
||||
renderPolygonLabels(
|
||||
context = context,
|
||||
labels = RidingStat.entries.toList().map { stat ->
|
||||
if (statLabelsHovered(pentagonVerticesOffset, pMouseX, pMouseY))
|
||||
"${floor((pokemon.getRideStat(selectedBehaviour.key, stat) / (selectedBehaviour.value.stats[stat]?.endInclusive ?: 1)) * 100)}%".text()
|
||||
else floor(pokemon.getRideStat(selectedBehaviour.key, stat)).toString().text()
|
||||
},
|
||||
verticesOffset = pentagonVerticesOffset,
|
||||
offsetY = 5.5
|
||||
)
|
||||
}
|
||||
|
||||
} else {
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = statsChartResource,
|
||||
x= (x + 25.5) / SCALE,
|
||||
y = (y + 22) / SCALE,
|
||||
width = 166,
|
||||
height = 192,
|
||||
scale = SCALE
|
||||
)
|
||||
|
||||
when (statOptions.get(statTabIndex)) {
|
||||
STATS -> drawStatPolygon(
|
||||
listOf(
|
||||
pokemon.maxHealth,
|
||||
pokemon.attack,
|
||||
pokemon.defence,
|
||||
pokemon.speed,
|
||||
pokemon.specialDefence,
|
||||
pokemon.specialAttack
|
||||
).map { it / 400F },
|
||||
colour = Vector3f(50F/255F, 215F/255F, 1F)
|
||||
)
|
||||
IV -> drawStatPolygon(
|
||||
statLabels.values.map { pokemon.ivs.getEffectiveBattleIV(it) / 31F },
|
||||
colour = Vector3f(216F/255, 100F/255, 1F)
|
||||
)
|
||||
EV -> drawStatPolygon(
|
||||
statLabels.values.map { (pokemon.evs[it]?.toFloat() ?: 0F) / 252F },
|
||||
colour = Vector3f(1F, 1F, 100F/255F)
|
||||
)
|
||||
}
|
||||
|
||||
val labelsHovered = statLabelsHovered(hexagonVerticesOffset, pMouseX, pMouseY)
|
||||
|
||||
val labels = statLabels.map { stat ->
|
||||
if (labelsHovered) {
|
||||
when (statOptions.get(statTabIndex)) {
|
||||
IV -> {
|
||||
"${
|
||||
if (pokemon.ivs.isHyperTrained(stat.value)) "${pokemon.ivs[stat.value]} (${pokemon.ivs.hyperTrainedIVs[stat.value]})"
|
||||
else pokemon.ivs[stat.value].toString()
|
||||
}/31".text()
|
||||
}
|
||||
EV -> "${pokemon.evs.getOrDefault(stat.value)}/252".text()
|
||||
else -> stat.key
|
||||
}
|
||||
} else { stat.key }
|
||||
}
|
||||
|
||||
// Stat Labels
|
||||
renderPolygonLabels(
|
||||
context = context,
|
||||
labels = labels,
|
||||
verticesOffset = hexagonVerticesOffset,
|
||||
enableColour = true
|
||||
)
|
||||
|
||||
// Stat Values
|
||||
renderPolygonLabels(
|
||||
context = context,
|
||||
labels = statValuesAsText(
|
||||
statLabels.values.toList(),
|
||||
labelsHovered
|
||||
),
|
||||
verticesOffset = hexagonVerticesOffset,
|
||||
offsetY = 5.5
|
||||
)
|
||||
|
||||
// Nature-modified Stat Icons
|
||||
if (statOptions.get(statTabIndex) == STATS) {
|
||||
val nature = pokemon.effectiveNature
|
||||
renderModifiedStatIcon(matrices, nature.increasedStat, true)
|
||||
renderModifiedStatIcon(matrices, nature.decreasedStat, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Stat type select bar
|
||||
val hasRideBehaviour = pokemon.form.riding.behaviours != null
|
||||
val startPosX = x + if (hasRideBehaviour) 23 else 31
|
||||
val statTabWidth = if (hasRideBehaviour) STAT_TAB_WIDTH_6 else STAT_TAB_WIDTH_5
|
||||
|
||||
statOptions.forEachIndexed { index, stat ->
|
||||
val statKey = if (stat == STATS) "" else ".$stat"
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = lang("ui.stats$statKey").bold(),
|
||||
x = startPosX + (statTabWidth * index),
|
||||
y = y + 143,
|
||||
scale = SCALE,
|
||||
colour = if (statOptions.get(statTabIndex) == stat) WHITE else GREY,
|
||||
centered = true
|
||||
when (statOptions.get(statTabIndex)) {
|
||||
STATS -> drawStatHexagon(
|
||||
mapOf(
|
||||
Stats.HP to pokemon.maxHealth,
|
||||
Stats.ATTACK to pokemon.attack,
|
||||
Stats.DEFENCE to pokemon.defence,
|
||||
Stats.SPECIAL_ATTACK to pokemon.specialAttack,
|
||||
Stats.SPECIAL_DEFENCE to pokemon.specialDefence,
|
||||
Stats.SPEED to pokemon.speed
|
||||
),
|
||||
colour = Vector3f(50F/255, 215F/255F, 1F),
|
||||
maximum = 400
|
||||
)
|
||||
IV -> drawStatHexagon(
|
||||
effectiveBattleIVs,
|
||||
colour = Vector3f(216F/255, 100F/255, 1F),
|
||||
maximum = 31
|
||||
)
|
||||
EV -> drawStatHexagon(
|
||||
pokemon.evs.associate { it.key to it.value },
|
||||
colour = Vector3f(1F, 1F, 100F/255),
|
||||
maximum = 252
|
||||
)
|
||||
}
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = statsLabel.bold(),
|
||||
x = x + 31,
|
||||
y = y + 143,
|
||||
scale = SCALE,
|
||||
colour = if (statOptions.get(statTabIndex) == STATS) WHITE else GREY,
|
||||
centered = true
|
||||
)
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = ivLabel.bold(),
|
||||
x = x + 55,
|
||||
y = y + 143,
|
||||
scale = SCALE,
|
||||
colour = if (statOptions.get(statTabIndex) == IV) WHITE else GREY,
|
||||
centered = true
|
||||
)
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = evLabel.bold(),
|
||||
x = x + 79,
|
||||
y = y + 143,
|
||||
scale = SCALE,
|
||||
colour = if (statOptions.get(statTabIndex) == EV) WHITE else GREY,
|
||||
centered = true
|
||||
)
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = otherLabel.bold(),
|
||||
x = x + 103,
|
||||
y = y + 143,
|
||||
scale = SCALE,
|
||||
colour = if (statOptions.get(statTabIndex) == OTHER) WHITE else GREY,
|
||||
centered = true
|
||||
)
|
||||
|
||||
val paddingLeft = (WIDTH - ((statOptions.size + 1) * statTabWidth)) / 2
|
||||
blitk(
|
||||
matrixStack = context.pose(),
|
||||
texture = tabMarkerResource,
|
||||
x= (startPosX + (statTabIndex * statTabWidth) - (MARKER_WIDTH / 4)) / SCALE,
|
||||
x= ((x + paddingLeft + ((statTabIndex + 1) * statTabWidth)) / SCALE) - 2,
|
||||
y = (y + 140) / SCALE,
|
||||
width = MARKER_WIDTH,
|
||||
width = 8,
|
||||
height = 4,
|
||||
scale = SCALE
|
||||
scale = SCALE,
|
||||
)
|
||||
|
||||
if (renderChart) {
|
||||
// Stat Labels
|
||||
renderTextAtVertices(
|
||||
context = context,
|
||||
hp = hpLabel.bold(),
|
||||
spAtk = spAtkLabel.bold(),
|
||||
atk = atkLabel.bold(),
|
||||
spDef = spDefLabel.bold(),
|
||||
def = defLabel.bold(),
|
||||
speed = speedLabel.bold()
|
||||
)
|
||||
|
||||
// Stat Values
|
||||
renderTextAtVertices(
|
||||
context = context,
|
||||
offsetY = 5.5,
|
||||
enableColour = false,
|
||||
hp = getStatValueAsText(Stats.HP),
|
||||
spAtk = getStatValueAsText(Stats.SPECIAL_ATTACK),
|
||||
atk = getStatValueAsText(Stats.ATTACK),
|
||||
spDef = getStatValueAsText(Stats.SPECIAL_DEFENCE),
|
||||
def = getStatValueAsText(Stats.DEFENCE),
|
||||
speed = getStatValueAsText(Stats.SPEED)
|
||||
)
|
||||
|
||||
// Nature-modified Stat Icons
|
||||
if (statOptions.get(statTabIndex) == STATS) {
|
||||
val nature = pokemon.effectiveNature
|
||||
renderModifiedStatIcon(matrices, nature.increasedStat, true)
|
||||
renderModifiedStatIcon(matrices, nature.decreasedStat, false)
|
||||
}
|
||||
} else {
|
||||
var drawY = y + 11
|
||||
|
||||
drawFriendship(x + 5, drawY, matrices, context, pokemon.friendship)
|
||||
drawY += 30
|
||||
|
||||
drawFullness(x + 5, drawY, matrices, context, pokemon)
|
||||
drawY += 30
|
||||
|
||||
for (renderableFeature in renderableFeatures) {
|
||||
val rendered = renderableFeature.render(
|
||||
GuiGraphics = context,
|
||||
x = x + 5F,
|
||||
y = drawY.toFloat(),
|
||||
pokemon = pokemon
|
||||
)
|
||||
|
||||
if (rendered) {
|
||||
drawY += 30
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun mouseClicked(pMouseX: Double, pMouseY: Double, pButton: Int): Boolean {
|
||||
val index = getTabIndexFromPos(pMouseX, pMouseY)
|
||||
// Only play sound here as the rest of the widget is meant to be silent
|
||||
if (index in 0 until statOptions.size && statTabIndex != index) {
|
||||
if (index in 0..4 && statTabIndex != index) {
|
||||
statTabIndex = index
|
||||
Minecraft.getInstance().soundManager.play(SimpleSoundInstance.forUI(CobblemonSounds.GUI_CLICK, 1.0F))
|
||||
}
|
||||
|
||||
if (statOptions.get(statTabIndex) == RIDE && ((pokemon.riding.behaviours?.size ?: 0) > 1) && centerHovered(pMouseX, pMouseY)) {
|
||||
rideBehaviourIndex = (rideBehaviourIndex + 1) % (pokemon.riding.behaviours?.size ?: 1)
|
||||
Minecraft.getInstance().soundManager.play(SimpleSoundInstance.forUI(CobblemonSounds.GUI_CLICK, 1.0F))
|
||||
}
|
||||
|
||||
return super.mouseClicked(pMouseX, pMouseY, pButton)
|
||||
}
|
||||
|
||||
private fun statValuesAsText(stats: List<Stat>, asPercent: Boolean): List<MutableComponent> {
|
||||
return stats.map { stat ->
|
||||
when (statOptions.get(statTabIndex)) {
|
||||
STATS -> (if (stat == Stats.HP) "${pokemon.currentHealth} / ${pokemon.maxHealth}" else pokemon.getStat(stat).toString()).text()
|
||||
IV -> {
|
||||
(if (asPercent) {
|
||||
"${floor((((if (pokemon.ivs.isHyperTrained(stat)) pokemon.ivs.hyperTrainedIVs[stat] else pokemon.ivs[stat]) ?: 0) / 31.0) * 100)}%"
|
||||
} else {
|
||||
if (pokemon.ivs.isHyperTrained(stat)) "${pokemon.ivs[stat]} (${pokemon.ivs.hyperTrainedIVs[stat]})"
|
||||
else pokemon.ivs[stat].toString()
|
||||
}).text()
|
||||
}
|
||||
EV -> {
|
||||
(if (asPercent) "${floor((pokemon.evs.getOrDefault(stat) / 252.0) * 100)}%"
|
||||
else pokemon.evs.getOrDefault(stat).toString()).text()
|
||||
}
|
||||
else -> "0".text()
|
||||
}
|
||||
private fun getStatValueAsText(stat: Stat): MutableComponent {
|
||||
val value = when (statOptions.get(statTabIndex)) {
|
||||
STATS -> if (stat == Stats.HP) "${pokemon.currentHealth} / ${pokemon.maxHealth}" else pokemon.getStat(stat).toString()
|
||||
IV -> if (pokemon.ivs.isHyperTrained(stat)) "${pokemon.ivs[stat]} (${pokemon.ivs.hyperTrainedIVs[stat]})" else pokemon.ivs[stat].toString()
|
||||
EV -> pokemon.evs.getOrDefault(stat).toString()
|
||||
else -> "0"
|
||||
}
|
||||
return value.text()
|
||||
}
|
||||
|
||||
private fun renderModifiedStatIcon(pPoseStack: PoseStack, stat: Stat?, increasedStat: Boolean) {
|
||||
@@ -531,7 +534,7 @@ class StatWidget(
|
||||
}
|
||||
}
|
||||
|
||||
private fun getModifiedStatColour(stat: Stat?, enableColour: Boolean): Int {
|
||||
private fun getModifiedStatColour(stat: Stat, enableColour: Boolean): Int {
|
||||
if (statOptions.get(statTabIndex) == STATS && enableColour) {
|
||||
val nature = pokemon.effectiveNature
|
||||
|
||||
@@ -541,38 +544,81 @@ class StatWidget(
|
||||
return WHITE
|
||||
}
|
||||
|
||||
private fun renderPolygonLabels(context: GuiGraphics, labels: List<MutableComponent>, verticesOffset: List<Pair<Double, Double>>, offsetY: Double = 0.0, enableColour: Boolean = false) {
|
||||
if (labels.size != verticesOffset.size) return
|
||||
private fun renderTextAtVertices(
|
||||
context: GuiGraphics,
|
||||
offsetY: Double = 0.0,
|
||||
enableColour: Boolean = true,
|
||||
hp: MutableComponent,
|
||||
spAtk: MutableComponent,
|
||||
atk: MutableComponent,
|
||||
spDef: MutableComponent,
|
||||
def: MutableComponent,
|
||||
speed: MutableComponent
|
||||
) {
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = hp,
|
||||
x = x + 67,
|
||||
y = y + 10.5 + offsetY,
|
||||
scale = SCALE,
|
||||
colour = getModifiedStatColour(Stats.HP, enableColour),
|
||||
centered = true
|
||||
)
|
||||
|
||||
labels.forEachIndexed { index, label ->
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = label,
|
||||
x = x + verticesOffset[index].first,
|
||||
y = y + verticesOffset[index].second + offsetY,
|
||||
scale = SCALE,
|
||||
colour = getModifiedStatColour(statLabels[label], enableColour),
|
||||
centered = true
|
||||
)
|
||||
}
|
||||
}
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = spAtk,
|
||||
x = x + 12,
|
||||
y = y + 42.5 + offsetY,
|
||||
scale = SCALE,
|
||||
colour = getModifiedStatColour(Stats.SPECIAL_ATTACK, enableColour),
|
||||
centered = true
|
||||
)
|
||||
|
||||
private fun centerHovered(pMouseX: Number, pMouseY: Number): Boolean {
|
||||
return (pMouseX.toInt() in (x + 44)..(x + 90)) && (pMouseY.toInt() in (y + 47)..(y + 93))
|
||||
}
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = atk,
|
||||
x = x + 122,
|
||||
y = y + 42.5 + offsetY,
|
||||
scale = SCALE,
|
||||
colour = getModifiedStatColour(Stats.ATTACK,enableColour),
|
||||
centered = true
|
||||
)
|
||||
|
||||
private fun statLabelsHovered(labelOffsets: List<Pair<Double, Double>>, mouseX: Int, mouseY: Int): Boolean {
|
||||
return labelOffsets.any { pos ->
|
||||
(mouseX.toDouble() in (x + pos.first - 12)..(x + pos.first + 12))
|
||||
&& (mouseY.toDouble() in (y + pos.second - 1)..(y + pos.second + 10))
|
||||
}
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = spDef,
|
||||
x = x + 12,
|
||||
y = y + 93.5 + offsetY,
|
||||
scale = SCALE,
|
||||
colour = getModifiedStatColour(Stats.SPECIAL_DEFENCE, enableColour),
|
||||
centered = true
|
||||
)
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = def,
|
||||
x = x + 122,
|
||||
y = y + 93.5 + offsetY,
|
||||
scale = SCALE,
|
||||
colour = getModifiedStatColour(Stats.DEFENCE, enableColour),
|
||||
centered = true
|
||||
)
|
||||
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = speed,
|
||||
x = x + 67,
|
||||
y = y + 124.5 + offsetY,
|
||||
scale = SCALE,
|
||||
colour = getModifiedStatColour(Stats.SPEED, enableColour),
|
||||
centered = true
|
||||
)
|
||||
}
|
||||
|
||||
private fun getTabIndexFromPos(mouseX: Double, mouseY: Double): Int {
|
||||
val hasRideBehaviour = pokemon.form.riding.behaviours != null
|
||||
val left = x + if (hasRideBehaviour) ((23 + 1) / 2).toFloat() else ((31 + 1) / 2).toFloat()
|
||||
val statTabWidth = if (hasRideBehaviour) STAT_TAB_WIDTH_6 else STAT_TAB_WIDTH_5
|
||||
|
||||
val paddingLeft = ((WIDTH - ((statOptions.size + 1) * statTabWidth)) / 2.0) + (statTabWidth / 2)
|
||||
val left = x + paddingLeft
|
||||
val top = y + 140.0
|
||||
if (mouseX in left..(left + (statTabWidth * (statOptions.size + 1))) && mouseY in top..(top + 9.0)) {
|
||||
var startX = left
|
||||
@@ -585,4 +631,4 @@ class StatWidget(
|
||||
}
|
||||
return -1
|
||||
}
|
||||
}
|
||||
}
|
||||
-53
@@ -1,53 +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.summary.widgets.screens.stats.features
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.summary.featurerenderers.BarSummarySpeciesFeatureRenderer
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
|
||||
class FriendshipFeatureRenderer(
|
||||
val selectedPokemon: Pokemon
|
||||
) : BarSummarySpeciesFeatureRenderer(
|
||||
"friendship",
|
||||
lang("ui.stats.friendship"),
|
||||
cobblemonResource("textures/gui/summary/summary_stats_other_bar.png"),
|
||||
cobblemonResource("textures/gui/summary/summary_stats_friendship_overlay.png"),
|
||||
selectedPokemon,
|
||||
0,
|
||||
255,
|
||||
selectedPokemon.friendship
|
||||
) {
|
||||
override fun render(guiGraphics: GuiGraphics, x: Float, y: Float, pokemon: Pokemon): Boolean {
|
||||
renderElement(guiGraphics, x, y, pokemon)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun renderBar(guiGraphics: GuiGraphics, x: Float, y: Float, barValue: Int, barRatio: Float, barWidth: Int) {
|
||||
val red = 1
|
||||
val green: Number = if (barValue >= 160) 0.28 else 0.56
|
||||
val blue: Number = if (barValue >= 160) 0.4 else 0.64
|
||||
|
||||
blitk(
|
||||
matrixStack = guiGraphics.pose(),
|
||||
texture = CobblemonResources.WHITE,
|
||||
x = x + 3,
|
||||
y = y + 13,
|
||||
height = 10,
|
||||
width = barWidth,
|
||||
red = red,
|
||||
green = green,
|
||||
blue = blue
|
||||
)
|
||||
}
|
||||
}
|
||||
-55
@@ -1,55 +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.summary.widgets.screens.stats.features
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.summary.featurerenderers.BarSummarySpeciesFeatureRenderer
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
|
||||
class FullnessFeatureRenderer(
|
||||
val selectedPokemon: Pokemon
|
||||
) : BarSummarySpeciesFeatureRenderer(
|
||||
"fullness",
|
||||
lang("ui.stats.fullness"),
|
||||
cobblemonResource("textures/gui/summary/summary_stats_other_bar.png"),
|
||||
cobblemonResource("textures/gui/summary/summary_stats_fullness_overlay.png"),
|
||||
selectedPokemon,
|
||||
0,
|
||||
selectedPokemon.getMaxFullness(),
|
||||
selectedPokemon.currentFullness
|
||||
) {
|
||||
override fun render(guiGraphics: GuiGraphics, x: Float, y: Float, pokemon: Pokemon): Boolean {
|
||||
renderElement(guiGraphics, x, y, pokemon)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun renderBar(guiGraphics: GuiGraphics, x: Float, y: Float, barValue: Int, barRatio: Float, barWidth: Int) {
|
||||
val (red, green, blue) = when {
|
||||
barRatio <= 0.33 -> Triple(120F/255F, 200F/255F, 80F/255F) // Green
|
||||
barRatio <= 0.66 -> Triple(240F/255F, 200F/255F, 65F/255F) // Yellow
|
||||
else -> Triple(230F/255F, 80F/255F, 65F/255F) // Red
|
||||
}
|
||||
|
||||
blitk(
|
||||
matrixStack = guiGraphics.pose(),
|
||||
texture = CobblemonResources.WHITE,
|
||||
x = x + 3,
|
||||
y = y + 13,
|
||||
height = 10,
|
||||
width = barWidth,
|
||||
red = red,
|
||||
green = green,
|
||||
blue = blue
|
||||
)
|
||||
}
|
||||
}
|
||||
-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.client.net.data
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonRideSettings
|
||||
import com.cobblemon.mod.common.api.net.ServerNetworkPacketHandler
|
||||
import com.cobblemon.mod.common.net.messages.client.data.RideSettingsSyncPacket
|
||||
import net.minecraft.server.MinecraftServer
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
object RideSettingsSyncHandler : ServerNetworkPacketHandler<RideSettingsSyncPacket> {
|
||||
override fun handle(packet: RideSettingsSyncPacket, server: MinecraftServer, player: ServerPlayer) {
|
||||
CobblemonRideSettings.bird = packet.bird
|
||||
CobblemonRideSettings.glider = packet.glider
|
||||
CobblemonRideSettings.helicopter = packet.helicopter
|
||||
CobblemonRideSettings.hover = packet.hover
|
||||
CobblemonRideSettings.jet = packet.jet
|
||||
CobblemonRideSettings.rocket = packet.rocket
|
||||
|
||||
CobblemonRideSettings.horse = packet.horse
|
||||
CobblemonRideSettings.minekart = packet.minekart
|
||||
CobblemonRideSettings.vehicle = packet.vehicle
|
||||
|
||||
CobblemonRideSettings.boat = packet.boat
|
||||
CobblemonRideSettings.burst = packet.burst
|
||||
CobblemonRideSettings.dolphin = packet.dolphin
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.net.data
|
||||
|
||||
import com.cobblemon.mod.common.api.net.ClientNetworkPacketHandler
|
||||
import com.cobblemon.mod.common.data.CobblemonDataProvider
|
||||
import com.cobblemon.mod.common.net.messages.client.data.UnlockReloadPacket
|
||||
import net.minecraft.client.Minecraft
|
||||
|
||||
internal object UnlockReloadPacketHandler : ClientNetworkPacketHandler<UnlockReloadPacket> {
|
||||
override fun handle(packet: UnlockReloadPacket, client: Minecraft) {
|
||||
CobblemonDataProvider.canReload = true
|
||||
}
|
||||
}
|
||||
-70
@@ -1,70 +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.persisted
|
||||
|
||||
import com.cobblemon.mod.common.config.CobblemonConfig
|
||||
import java.io.BufferedReader
|
||||
import java.io.BufferedWriter
|
||||
import java.io.FileInputStream
|
||||
import java.io.FileWriter
|
||||
import java.io.InputStreamReader
|
||||
import java.nio.file.Paths
|
||||
import kotlin.io.path.exists
|
||||
import net.minecraft.client.CameraType
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
object ClientPersistedData {
|
||||
|
||||
val gson = CobblemonConfig.GSON
|
||||
|
||||
val snapshotsPath = Paths.get("cobblemon").resolve("snapshots.json")
|
||||
val ridingPerspectivesPath = Paths.get("cobblemon").resolve("riding_perspectives.json")
|
||||
|
||||
var ridingPerspectives: RidingPerspectiveData = readRidingPerspectivesData() ?: RidingPerspectiveData()
|
||||
|
||||
fun readSnapshotsData() : SnapshotAcknowledgementData? {
|
||||
if (snapshotsPath.exists()) {
|
||||
BufferedReader(InputStreamReader(FileInputStream(snapshotsPath.toFile()))).use { reader ->
|
||||
return gson.fromJson(reader, SnapshotAcknowledgementData::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
fun writeSnapshotsData(data: SnapshotAcknowledgementData) {
|
||||
snapshotsPath.toFile().parentFile.mkdirs()
|
||||
BufferedWriter(FileWriter(snapshotsPath.toFile())).use { writer -> gson.toJson(data, writer) }
|
||||
}
|
||||
|
||||
fun readRidingPerspectivesData() : RidingPerspectiveData? {
|
||||
if (ridingPerspectivesPath.exists()) {
|
||||
BufferedReader(InputStreamReader(FileInputStream(ridingPerspectivesPath.toFile()))).use { reader ->
|
||||
return gson.fromJson(reader, RidingPerspectiveData::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
fun saveRidingPerspectivesData() {
|
||||
ridingPerspectivesPath.toFile().parentFile.mkdirs()
|
||||
BufferedWriter(FileWriter(ridingPerspectivesPath.toFile())).use { writer -> gson.toJson(ridingPerspectives, writer) }
|
||||
}
|
||||
|
||||
data class SnapshotAcknowledgementData(val version: String, val dontShowAgain: Boolean)
|
||||
data class RidingPerspectiveData(
|
||||
val perspectives: MutableMap<ResourceLocation, CameraType> = mutableMapOf()
|
||||
) {
|
||||
fun updatePerspective(key: ResourceLocation, cameraType: CameraType) {
|
||||
perspectives[key] = cameraType
|
||||
saveRidingPerspectivesData()
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-15
@@ -17,12 +17,10 @@ import com.cobblemon.mod.common.util.math.fromEulerXYZDegrees
|
||||
import com.mojang.blaze3d.platform.Lighting
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer
|
||||
import com.mojang.blaze3d.vertex.VertexMultiConsumer
|
||||
import net.minecraft.client.renderer.LightTexture
|
||||
import net.minecraft.client.renderer.MultiBufferSource
|
||||
import net.minecraft.client.renderer.RenderType
|
||||
import net.minecraft.client.renderer.texture.OverlayTexture
|
||||
import net.minecraft.core.component.DataComponents
|
||||
import net.minecraft.world.item.ItemDisplayContext
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import org.joml.Quaternionf
|
||||
@@ -48,6 +46,8 @@ class PokemonItemRenderer : CobblemonBuiltinItemRenderer {
|
||||
context.put(RenderContext.POSABLE_STATE, state)
|
||||
state.currentModel = model
|
||||
|
||||
val renderLayer = RenderType.entityCutout(VaryingModelRepository.getTexture(species.resourceIdentifier, state))
|
||||
|
||||
val transformations = positions[mode]!!
|
||||
|
||||
if (mode == ItemDisplayContext.GUI) {
|
||||
@@ -64,19 +64,7 @@ class PokemonItemRenderer : CobblemonBuiltinItemRenderer {
|
||||
val rotation = Quaternionf().fromEulerXYZDegrees(Vector3f(transformations.rotation.x, transformations.rotation.y, transformations.rotation.z))
|
||||
matrices.mulPose(rotation)
|
||||
rotation.conjugate()
|
||||
|
||||
val renderLayer = RenderType.entityCutout(VaryingModelRepository.getTexture(species.resourceIdentifier, state))
|
||||
val isEnchanted = stack.get(DataComponents.ENCHANTMENTS)?.isEmpty == false
|
||||
val vertexConsumer: VertexConsumer =
|
||||
if (isEnchanted) {
|
||||
VertexMultiConsumer.create(
|
||||
vertexConsumers.getBuffer(RenderType.entityGlintDirect()),
|
||||
vertexConsumers.getBuffer(renderLayer),
|
||||
)
|
||||
} else {
|
||||
vertexConsumers.getBuffer(renderLayer)
|
||||
}
|
||||
|
||||
val vertexConsumer: VertexConsumer = vertexConsumers.getBuffer(renderLayer)
|
||||
matrices.pushPose()
|
||||
val packedLight = if (mode == ItemDisplayContext.GUI) {
|
||||
LightTexture.pack(13, 13)
|
||||
|
||||
+1
-1
@@ -267,7 +267,7 @@ class TexturedModel {
|
||||
var counter = 0
|
||||
subParts.forEachIndexed { index, part ->
|
||||
parts[bone.name]!!.addOrReplaceChild(
|
||||
"%" + bone.name + "%" + counter++.toString(),
|
||||
bone.name + counter++.toString(),
|
||||
part,
|
||||
modelTransforms[index]
|
||||
)
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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.snapshots
|
||||
|
||||
import com.cobblemon.mod.common.config.CobblemonConfig
|
||||
import java.io.BufferedReader
|
||||
import java.io.BufferedWriter
|
||||
import java.io.FileInputStream
|
||||
import java.io.FileWriter
|
||||
import java.io.InputStreamReader
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
import kotlin.io.path.exists
|
||||
|
||||
object SnapshotAcknowledgementReader {
|
||||
|
||||
val gson = CobblemonConfig.GSON
|
||||
val target: Path = Paths.get("cobblemon").resolve("snapshots.json")
|
||||
|
||||
fun read() : SnapshotAcknowledgementData? {
|
||||
if (target.exists()) {
|
||||
BufferedReader(InputStreamReader(FileInputStream(target.toFile()))).use { reader ->
|
||||
return gson.fromJson(reader, SnapshotAcknowledgementData::class.java)
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
fun write(data: SnapshotAcknowledgementData) {
|
||||
target.toFile().parentFile.mkdirs()
|
||||
BufferedWriter(FileWriter(target.toFile())).use { writer -> gson.toJson(data, writer) }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
data class SnapshotAcknowledgementData(val version: String, val dontShowAgain: Boolean)
|
||||
+9
-2
@@ -11,6 +11,8 @@ package com.cobblemon.mod.common.client.tooltips
|
||||
import com.cobblemon.mod.common.CobblemonItemComponents
|
||||
import com.cobblemon.mod.common.CobblemonRecipeTypes
|
||||
import com.cobblemon.mod.common.api.cooking.Flavour
|
||||
import com.cobblemon.mod.common.api.cooking.Food
|
||||
import com.cobblemon.mod.common.api.cooking.PokePuffUtils
|
||||
import com.cobblemon.mod.common.api.cooking.Seasonings
|
||||
import com.cobblemon.mod.common.api.fishing.SpawnBait
|
||||
import com.cobblemon.mod.common.api.fishing.SpawnBaitEffects
|
||||
@@ -18,16 +20,20 @@ import com.cobblemon.mod.common.api.fishing.SpawnBaitUtils
|
||||
import com.cobblemon.mod.common.api.pokemon.egg.EggGroup
|
||||
import com.cobblemon.mod.common.api.text.*
|
||||
import com.cobblemon.mod.common.api.types.ElementalTypes
|
||||
import com.cobblemon.mod.common.item.components.FoodComponent
|
||||
import com.cobblemon.mod.common.item.crafting.CookingPotRecipe
|
||||
import com.cobblemon.mod.common.item.crafting.CookingPotRecipeBase
|
||||
import com.cobblemon.mod.common.item.interactive.PokerodItem
|
||||
import com.cobblemon.mod.common.pokemon.Gender
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.ChatFormatting
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.chat.Style
|
||||
import net.minecraft.world.effect.MobEffectInstance
|
||||
import net.minecraft.world.effect.MobEffectUtil
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.crafting.RecipeManager
|
||||
import net.minecraft.world.level.Level
|
||||
import java.text.DecimalFormat
|
||||
|
||||
val cookingPotRecipeAbsorbHeader by lazy { lang("item_class.cooking_pot_recipe_absorbs").gray() }
|
||||
@@ -115,7 +121,8 @@ fun generateAdditionalFlavorTooltip(flavours: Map<Flavour, Int>): MutableList<Co
|
||||
|
||||
val combinedFlavorsLine = Component.literal("")
|
||||
flavours.filter { it.key != Flavour.MILD }.forEach { (flavour, value) ->
|
||||
val flavourText = lang("seasoning_flavor.${flavour.name.lowercase()}").setStyle(Style.EMPTY.withColor(flavour.colour))
|
||||
var flavourText = lang("seasoning_flavor.${flavour.name.lowercase()}").withStyle(flavour.chatFormatting)
|
||||
|
||||
if (combinedFlavorsLine.string.isNotEmpty()) {
|
||||
combinedFlavorsLine.append(" ")
|
||||
}
|
||||
|
||||
@@ -9,60 +9,34 @@
|
||||
package com.cobblemon.mod.common.command
|
||||
|
||||
import com.cobblemon.mod.common.api.permission.CobblemonPermissions
|
||||
import com.cobblemon.mod.common.api.text.green
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.entity.npc.NPCEntity
|
||||
import com.cobblemon.mod.common.util.commandLang
|
||||
import com.cobblemon.mod.common.util.permission
|
||||
import com.cobblemon.mod.common.util.requiresWithPermission
|
||||
import com.cobblemon.mod.common.util.traceFirstEntityCollision
|
||||
import com.mojang.brigadier.Command
|
||||
import com.mojang.brigadier.CommandDispatcher
|
||||
import com.mojang.brigadier.context.CommandContext
|
||||
import net.minecraft.commands.CommandSourceStack
|
||||
import net.minecraft.commands.Commands
|
||||
import net.minecraft.commands.arguments.EntityArgument
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
object NPCDeleteCommand {
|
||||
fun register(dispatcher : CommandDispatcher<CommandSourceStack>) {
|
||||
dispatcher.register(
|
||||
Commands.literal("npcdelete")
|
||||
.permission(CobblemonPermissions.NPC_DELETE)
|
||||
.then(
|
||||
Commands.argument("target", EntityArgument.entity())
|
||||
.executes {context ->
|
||||
val source = context.source
|
||||
val entity = EntityArgument.getEntity(context, "target")
|
||||
execute(entity, source)
|
||||
}
|
||||
)
|
||||
.executes {context ->
|
||||
val source = context.source
|
||||
val player = source.player
|
||||
if (player == null) {
|
||||
source.sendSystemMessage(commandLang("npcdelete.not_player").red())
|
||||
return@executes 0
|
||||
}
|
||||
|
||||
val targetEntity = player.traceFirstEntityCollision(entityClass = NPCEntity::class.java)
|
||||
|
||||
if (targetEntity == null) {
|
||||
player.sendSystemMessage(commandLang("npcedit.non_npc").red())
|
||||
return@executes 0
|
||||
}
|
||||
execute(targetEntity, source)
|
||||
}
|
||||
|
||||
)
|
||||
.requiresWithPermission(CobblemonPermissions.NPC_DELETE) { it.player != null }
|
||||
.executes { execute(it, it.source.playerOrException) })
|
||||
}
|
||||
|
||||
private fun execute(entity: Entity, source: CommandSourceStack) : Int {
|
||||
if(entity !is NPCEntity){
|
||||
source.sendSystemMessage(commandLang("npcedit.non_npc").red())
|
||||
private fun execute(context: CommandContext<CommandSourceStack>, player: ServerPlayer) : Int {
|
||||
val targetEntity = player.traceFirstEntityCollision(entityClass = NPCEntity::class.java)
|
||||
if (targetEntity == null) {
|
||||
player.sendSystemMessage(commandLang("npcedit.non_npc").red())
|
||||
return 0
|
||||
}
|
||||
|
||||
entity.discard()
|
||||
source.sendSystemMessage(commandLang("npcdelete.deleted", entity.name.string).green())
|
||||
targetEntity.discard()
|
||||
return Command.SINGLE_SUCCESS
|
||||
}
|
||||
}
|
||||
@@ -15,13 +15,11 @@ import com.cobblemon.mod.common.client.gui.portrait.PortraitStyle
|
||||
import com.cobblemon.mod.common.config.constraint.IntConstraint
|
||||
import com.cobblemon.mod.common.pokeball.catching.calculators.CobblemonCaptureCalculator
|
||||
import com.cobblemon.mod.common.util.adapters.CaptureCalculatorAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.IdentifierAdapter
|
||||
import com.cobblemon.mod.common.util.adapters.IntRangeAdapter
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import kotlin.reflect.full.memberProperties
|
||||
import kotlin.reflect.jvm.isAccessible
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
class CobblemonConfig {
|
||||
companion object {
|
||||
@@ -31,7 +29,6 @@ class CobblemonConfig {
|
||||
.registerTypeAdapter(IntRange::class.java, IntRangeAdapter)
|
||||
.registerTypeAdapter(ItemDropMethod::class.java, ItemDropMethod.adapter)
|
||||
.registerTypeAdapter(CaptureCalculator::class.java, CaptureCalculatorAdapter)
|
||||
.registerTypeAdapter(ResourceLocation::class.java, IdentifierAdapter)
|
||||
.create()
|
||||
}
|
||||
|
||||
@@ -303,12 +300,6 @@ class CobblemonConfig {
|
||||
@CobblemonConfigField(Category.Riding, lang = "display_controls_duration_seconds")
|
||||
var displayControlSeconds = 3
|
||||
|
||||
@CobblemonConfigField(Category.Riding, lang = "infinite_ride_stamina")
|
||||
var infiniteRideStamina = false
|
||||
|
||||
@CobblemonConfigField(Category.Riding, lang = "remember_riding_camera")
|
||||
var rememberRidingCamera = true
|
||||
|
||||
@CobblemonConfigField(Category.Debug, lang = "enable_debug_keys")
|
||||
var enableDebugKeys = true
|
||||
|
||||
|
||||
@@ -10,22 +10,22 @@ package com.cobblemon.mod.common.data
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
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.CobblemonCallbacks
|
||||
import com.cobblemon.mod.common.CobblemonBehaviours
|
||||
import com.cobblemon.mod.common.CobblemonMechanics
|
||||
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
|
||||
import com.cobblemon.mod.common.api.data.DataProvider
|
||||
import com.cobblemon.mod.common.api.data.DataRegistry
|
||||
import com.cobblemon.mod.common.api.pokedex.Dexes
|
||||
import com.cobblemon.mod.common.api.dialogue.Dialogues
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents
|
||||
import com.cobblemon.mod.common.api.fishing.PokeRods
|
||||
import com.cobblemon.mod.common.api.fishing.SpawnBait
|
||||
import com.cobblemon.mod.common.api.fishing.SpawnBaitEffects
|
||||
import com.cobblemon.mod.common.api.fishing.PokeRods
|
||||
import com.cobblemon.mod.common.api.fossil.Fossils
|
||||
import com.cobblemon.mod.common.api.fossil.NaturalMaterials
|
||||
import com.cobblemon.mod.common.api.interaction.PokemonInteractions
|
||||
@@ -37,7 +37,6 @@ import com.cobblemon.mod.common.api.npc.NPCClasses
|
||||
import com.cobblemon.mod.common.api.npc.NPCPresets
|
||||
import com.cobblemon.mod.common.api.pokeball.PokeBalls
|
||||
import com.cobblemon.mod.common.api.pokedex.DexAdditions
|
||||
import com.cobblemon.mod.common.api.pokedex.Dexes
|
||||
import com.cobblemon.mod.common.api.pokedex.entry.DexEntries
|
||||
import com.cobblemon.mod.common.api.pokedex.entry.DexEntryAdditions
|
||||
import com.cobblemon.mod.common.api.pokemon.PokemonSpecies
|
||||
@@ -49,72 +48,73 @@ import com.cobblemon.mod.common.api.spawning.CobblemonSpawnPools
|
||||
import com.cobblemon.mod.common.api.spawning.CobblemonSpawnRules
|
||||
import com.cobblemon.mod.common.api.spawning.SpawnDetailPresets
|
||||
import com.cobblemon.mod.common.battles.BagItems
|
||||
import com.cobblemon.mod.common.net.messages.client.data.UnlockReloadPacket
|
||||
import com.cobblemon.mod.common.platform.events.PlatformEvents
|
||||
import com.cobblemon.mod.common.pokemon.SpeciesAdditions
|
||||
import com.cobblemon.mod.common.pokemon.properties.PropertiesCompletionProvider
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.ifClient
|
||||
import com.cobblemon.mod.common.util.server
|
||||
import java.util.UUID
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.server.packs.PackType
|
||||
import net.minecraft.server.packs.resources.ResourceManager
|
||||
import net.minecraft.server.packs.resources.ResourceManagerReloadListener
|
||||
import java.util.*
|
||||
|
||||
object CobblemonDataProvider : DataProvider {
|
||||
|
||||
internal var canReload = true
|
||||
// Both Forge n Fabric keep insertion order so if a registry depends on another simply register it after
|
||||
private val registries = linkedSetOf<DataRegistry>()
|
||||
private val reloadableRegistries = linkedSetOf<DataRegistry>()
|
||||
private val synchronizedPlayerIds = mutableListOf<UUID>()
|
||||
|
||||
private val scheduledActions = mutableMapOf<UUID, MutableList<() -> Unit>>()
|
||||
|
||||
fun registerDefaults() {
|
||||
this.register(CobblemonScripts, reloadable = true)
|
||||
this.register(SpeciesFeatures, reloadable = false)
|
||||
this.register(GlobalSpeciesFeatures, reloadable = false)
|
||||
this.register(SpeciesFeatureAssignments, reloadable = false)
|
||||
this.register(ActionEffects, reloadable = true)
|
||||
this.register(Moves, reloadable = false)
|
||||
this.register(Abilities, reloadable = false)
|
||||
this.register(CobblemonBehaviours, reloadable = false)
|
||||
this.register(PokemonSpecies, reloadable = false)
|
||||
this.register(SpeciesAdditions, reloadable = false)
|
||||
this.register(PokeBalls, reloadable = false)
|
||||
this.register(PropertiesCompletionProvider, reloadable = false)
|
||||
this.register(SpawnDetailPresets, reloadable = true)
|
||||
this.register(CobblemonSpawnRules, reloadable = true)
|
||||
this.register(CobblemonMechanics, reloadable = true)
|
||||
this.register(BagItems, reloadable = false)
|
||||
this.register(HeldItems, reloadable = false)
|
||||
this.register(Dialogues, reloadable = true)
|
||||
this.register(NaturalMaterials, reloadable = true)
|
||||
this.register(Fossils, reloadable = true)
|
||||
this.register(NPCPresets, reloadable = false)
|
||||
this.register(NPCClasses, reloadable = false)
|
||||
this.register(DexEntries, reloadable = false)
|
||||
this.register(DexEntryAdditions, reloadable = false)
|
||||
this.register(Dexes, reloadable = false)
|
||||
this.register(DexAdditions, reloadable = false)
|
||||
this.register(CobblemonCosmeticItems, reloadable = true)
|
||||
this.register(CobblemonCallbacks, reloadable = true)
|
||||
this.register(CobblemonUnlockableWallpapers, reloadable = true)
|
||||
this.register(Marks, reloadable = false)
|
||||
this.register(StarterDataLoader, reloadable = true)
|
||||
this.register(CobblemonScripts)
|
||||
this.register(SpeciesFeatures)
|
||||
this.register(GlobalSpeciesFeatures)
|
||||
this.register(SpeciesFeatureAssignments)
|
||||
this.register(ActionEffects)
|
||||
this.register(Moves)
|
||||
this.register(Abilities)
|
||||
this.register(CobblemonBehaviours)
|
||||
this.register(PokemonSpecies)
|
||||
this.register(SpeciesAdditions)
|
||||
this.register(PokeBalls)
|
||||
this.register(PropertiesCompletionProvider)
|
||||
this.register(SpawnDetailPresets)
|
||||
this.register(CobblemonSpawnRules)
|
||||
this.register(CobblemonMechanics)
|
||||
this.register(BagItems)
|
||||
this.register(HeldItems)
|
||||
this.register(Dialogues)
|
||||
this.register(NaturalMaterials)
|
||||
this.register(Fossils)
|
||||
this.register(NPCPresets)
|
||||
this.register(NPCClasses)
|
||||
this.register(DexEntries)
|
||||
this.register(DexEntryAdditions)
|
||||
this.register(Dexes)
|
||||
this.register(DexAdditions)
|
||||
this.register(CobblemonCosmeticItems)
|
||||
this.register(CobblemonCallbacks)
|
||||
this.register(CobblemonUnlockableWallpapers)
|
||||
this.register(Marks)
|
||||
this.register(StarterDataLoader)
|
||||
|
||||
CobblemonSpawnPools.load()
|
||||
this.register(PokeRods, reloadable = false)
|
||||
this.register(Berries, reloadable = false)
|
||||
this.register(Seasonings, reloadable = false)
|
||||
this.register(PokemonInteractions, reloadable = false)
|
||||
this.register(SpawnBaitEffects, reloadable = false)
|
||||
this.register(CobblemonRideSettings, reloadable = true)
|
||||
this.register(PokeRods)
|
||||
this.register(Berries)
|
||||
this.register(Seasonings)
|
||||
this.register(PokemonInteractions)
|
||||
this.register(SpawnBaitEffects)
|
||||
SpawnBait.Effects.setupEffects()
|
||||
|
||||
PlatformEvents.SERVER_PLAYER_LOGOUT.subscribe {
|
||||
synchronizedPlayerIds.remove(it.player.uuid)
|
||||
UnlockReloadPacket().sendToPlayer(it.player)
|
||||
}
|
||||
|
||||
ifClient {
|
||||
@@ -123,15 +123,12 @@ object CobblemonDataProvider : DataProvider {
|
||||
Cobblemon.implementation.registerResourceReloader(cobblemonResource("data_resources"), SimpleResourceReloader(PackType.SERVER_DATA), PackType.SERVER_DATA, emptyList())
|
||||
}
|
||||
|
||||
override fun <T : DataRegistry> register(registry: T, reloadable: Boolean): T {
|
||||
override fun <T : DataRegistry> register(registry: T): T {
|
||||
// Only send message once
|
||||
if (this.registries.isEmpty()) {
|
||||
LOGGER.info("Note: Cobblemon data registries are only loaded once per server instance as Pokémon species are not safe to reload.")
|
||||
}
|
||||
this.registries.add(registry)
|
||||
if (reloadable) {
|
||||
this.reloadableRegistries.add(registry)
|
||||
}
|
||||
LOGGER.info("Registered the {} registry", registry.id.toString())
|
||||
LOGGER.debug("Registered the {} registry of class {}", registry.id.toString(), registry::class.qualifiedName)
|
||||
return registry
|
||||
@@ -162,9 +159,15 @@ object CobblemonDataProvider : DataProvider {
|
||||
private class SimpleResourceReloader(private val type: PackType) : ResourceManagerReloadListener {
|
||||
override fun onResourceManagerReload(manager: ResourceManager) {
|
||||
// Check for a server running, this is due to the create a world screen triggering datapack reloads, these are fine to happen as many times as needed as players may be in the process of adding their datapacks.
|
||||
val reloadAllowed = server()?.isReady != true
|
||||
registries.filter { it.type == this.type && (reloadAllowed || it in reloadableRegistries) }
|
||||
val isInGame = server() != null
|
||||
if (isInGame && this.type == PackType.SERVER_DATA && !canReload) {
|
||||
return
|
||||
}
|
||||
registries.filter { it.type == this.type }
|
||||
.forEach { it.reload(manager) }
|
||||
if (isInGame && this.type == PackType.SERVER_DATA) {
|
||||
canReload = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
package com.cobblemon.mod.common.debug
|
||||
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.renderer.MultiBufferSource
|
||||
import net.minecraft.client.renderer.debug.DebugRenderer
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.Position
|
||||
import java.util.function.Consumer
|
||||
|
||||
object RidingDebugRenderer : DebugRenderer.SimpleDebugRenderer {
|
||||
var enabled = false
|
||||
|
||||
override fun render(
|
||||
poseStack: PoseStack,
|
||||
buffer: MultiBufferSource,
|
||||
camX: Double,
|
||||
camY: Double,
|
||||
camZ: Double
|
||||
) {
|
||||
val minecraft = Minecraft.getInstance() ?: return
|
||||
val vehicle = minecraft.player?.vehicle
|
||||
if (vehicle != null && vehicle is PokemonEntity) {
|
||||
DebugRenderer.renderFloatingText(poseStack, buffer, "riding", camX, camY, camZ, -1, 1f, false, 0.5f, true)
|
||||
renderRidingInfo(vehicle, poseStack, buffer)
|
||||
}
|
||||
}
|
||||
|
||||
private fun renderRidingInfo(vehicle: PokemonEntity, poseStack: PoseStack, buffer: MultiBufferSource) {
|
||||
val ridingController = vehicle.ridingController
|
||||
if (ridingController != null) {
|
||||
var i = 0
|
||||
ridingController.context?.let { context ->
|
||||
val debugString = "Currently active: ${context.behaviour}"
|
||||
renderTextOverVehicle(poseStack, buffer, vehicle.position(), i, debugString, -1, 0.03f)
|
||||
i++
|
||||
}
|
||||
ridingController.behaviours.forEach { (style, settings) ->
|
||||
val debugString = "Available: $style"
|
||||
renderTextOverVehicle(poseStack, buffer, vehicle.position(), i, debugString, -1, 0.03f)
|
||||
i++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun renderTextOverVehicle(poseStack: PoseStack, buffer: MultiBufferSource, pos: Position, layer: Int, text: String, color: Int, scale: Float) {
|
||||
val blockPos = BlockPos.containing(pos)
|
||||
val x = blockPos.x.toDouble() + 0.5
|
||||
val y = blockPos.y.toDouble() + 2.4 + layer * 0.25
|
||||
val z = blockPos.z.toDouble() + 0.5
|
||||
DebugRenderer.renderFloatingText(poseStack, buffer, text, x, y, z, color, scale, false, 0.5f, true)
|
||||
}
|
||||
|
||||
fun clientHandler(enabled: Boolean) {
|
||||
this.enabled = enabled
|
||||
}
|
||||
}
|
||||
@@ -21,9 +21,7 @@ import net.minecraft.world.level.material.FluidState
|
||||
interface OmniPathingEntity {
|
||||
fun canWalk(): Boolean
|
||||
fun canSwimInWater(): Boolean
|
||||
fun canWalkOnWater(): Boolean
|
||||
fun canSwimInLava(): Boolean
|
||||
fun canWalkOnLava(): Boolean
|
||||
fun canSwimUnderFluid(fluidState: FluidState): Boolean
|
||||
fun canFly(): Boolean
|
||||
fun isFlying(): Boolean
|
||||
|
||||
@@ -49,7 +49,7 @@ enum class PoseType {
|
||||
val UI_POSES = EnumSet.of(PROFILE, PORTRAIT)
|
||||
val MOVING_POSES = EnumSet.of(WALK, SWIM, FLY)
|
||||
val STATIONARY_POSES = EnumSet.of(STAND, FLOAT, HOVER)
|
||||
val NO_GRAV_POSES = EnumSet.of(FLY, HOVER, SWIM)
|
||||
val NO_GRAV_POSES = EnumSet.of(FLY, HOVER, FLOAT, SWIM)
|
||||
|
||||
fun identified() : List<ResourceLocation> {
|
||||
return ALL_POSES.stream()
|
||||
|
||||
-125
@@ -1,125 +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.entity.ai
|
||||
|
||||
import com.cobblemon.mod.common.entity.OmniPathingEntity
|
||||
import net.minecraft.core.BlockPos
|
||||
import net.minecraft.tags.FluidTags
|
||||
import net.minecraft.world.entity.PathfinderMob
|
||||
import net.minecraft.world.entity.ai.util.GoalUtils
|
||||
import net.minecraft.world.entity.ai.util.RandomPos
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import java.util.*
|
||||
import java.util.function.Supplier
|
||||
import java.util.function.ToDoubleFunction
|
||||
|
||||
/*
|
||||
*
|
||||
* This is a rewrite of Minecraft's LandRandomPos tuned for
|
||||
* water and lava walkers.
|
||||
* The only real difference is movePosUpOutOfSolid() which
|
||||
* moves the target pos out of liquids
|
||||
*
|
||||
* */
|
||||
class CobblemonRandomSurfacePos {
|
||||
companion object {
|
||||
fun getPos(mob: PathfinderMob, radius: Int, verticalRange: Int): Vec3? {
|
||||
Objects.requireNonNull(mob)
|
||||
return getPos(
|
||||
mob,
|
||||
radius,
|
||||
verticalRange,
|
||||
{ pos: BlockPos? ->
|
||||
if (pos != null) {
|
||||
mob.getWalkTargetValue(pos).toDouble()
|
||||
}
|
||||
0.0
|
||||
})
|
||||
}
|
||||
|
||||
fun getPos(mob: PathfinderMob, radius: Int, yRange: Int, toDoubleFunction: ToDoubleFunction<BlockPos?>): Vec3? {
|
||||
val bl = GoalUtils.mobRestricted(mob, radius)
|
||||
return RandomPos.generateRandomPos(Supplier {
|
||||
val blockPos = RandomPos.generateRandomDirection(mob.getRandom(), radius, yRange)
|
||||
val blockPos2 = generateRandomPosTowardDirection(mob, radius, bl, blockPos)
|
||||
if (blockPos2 == null) null else movePosUpOutOfSolid(mob, blockPos2)
|
||||
}, toDoubleFunction)
|
||||
}
|
||||
|
||||
fun getPosTowards(mob: PathfinderMob, radius: Int, yRange: Int, vectorPosition: Vec3): Vec3? {
|
||||
val vec3 = vectorPosition.subtract(mob.getX(), mob.getY(), mob.getZ())
|
||||
val bl = GoalUtils.mobRestricted(mob, radius)
|
||||
return getPosInDirection(mob, radius, yRange, vec3, bl)
|
||||
}
|
||||
private fun getPosInDirection(
|
||||
mob: PathfinderMob,
|
||||
radius: Int,
|
||||
yRange: Int,
|
||||
vectorPosition: Vec3,
|
||||
shortCircuit: Boolean
|
||||
): Vec3? {
|
||||
return RandomPos.generateRandomPos(mob, Supplier {
|
||||
val blockPos: BlockPos? =
|
||||
RandomPos.generateRandomDirectionWithinRadians(
|
||||
mob.getRandom(),
|
||||
radius,
|
||||
yRange,
|
||||
0,
|
||||
vectorPosition.x,
|
||||
vectorPosition.z,
|
||||
(Math.PI.toFloat() / 2f).toDouble()
|
||||
)
|
||||
if (blockPos == null) {
|
||||
return@Supplier null
|
||||
} else {
|
||||
val blockPos2: BlockPos? =
|
||||
generateRandomPosTowardDirection(
|
||||
mob,
|
||||
radius,
|
||||
shortCircuit,
|
||||
blockPos
|
||||
)
|
||||
return@Supplier if (blockPos2 == null) null else movePosUpOutOfSolid(
|
||||
mob,
|
||||
blockPos2
|
||||
)
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
fun generateRandomPosTowardDirection(
|
||||
mob: PathfinderMob,
|
||||
radius: Int,
|
||||
shortCircuit: Boolean,
|
||||
pos: BlockPos
|
||||
): BlockPos? {
|
||||
val blockPos = RandomPos.generateRandomPosTowardDirection(mob, radius, mob.getRandom(), pos)
|
||||
return if (!GoalUtils.isOutsideLimits(blockPos, mob) && !GoalUtils.isRestricted(
|
||||
shortCircuit,
|
||||
mob,
|
||||
blockPos
|
||||
) && !GoalUtils.isNotStable(mob.getNavigation(), blockPos)
|
||||
) blockPos else null
|
||||
}
|
||||
|
||||
fun movePosUpOutOfSolid(mob: PathfinderMob, pos: BlockPos): BlockPos? {
|
||||
var pos = pos
|
||||
pos = RandomPos.moveUpOutOfSolid(
|
||||
pos,
|
||||
mob.level().maxBuildHeight
|
||||
) { blockPos: BlockPos ->
|
||||
if (GoalUtils.isSolid(mob, blockPos)) true
|
||||
val fluidState = mob.level().getFluidState(blockPos)
|
||||
!fluidState.isEmpty && (mob !is OmniPathingEntity || ((mob.canWalkOnWater() && fluidState.type == FluidTags.WATER) || (mob.canWalkOnLava() && fluidState.type == FluidTags.LAVA)))
|
||||
}
|
||||
return if (!GoalUtils.hasMalus(mob, pos)) pos else null
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ import net.minecraft.world.level.pathfinder.Path
|
||||
import net.minecraft.world.level.pathfinder.PathComputationType
|
||||
import net.minecraft.world.level.pathfinder.PathFinder
|
||||
import net.minecraft.world.level.pathfinder.PathType
|
||||
import net.minecraft.world.level.pathfinder.WalkNodeEvaluator
|
||||
import net.minecraft.world.phys.Vec3
|
||||
import kotlin.math.PI
|
||||
import kotlin.math.abs
|
||||
@@ -132,7 +133,7 @@ class OmniPathNavigation(val world: Level, val entity: Mob) : GroundPathNavigati
|
||||
val f = abs(mob.z - targetVec3d.z)
|
||||
val closeEnough = d < maxDistanceToWaypoint.toDouble()
|
||||
&& f < this.maxDistanceToWaypoint.toDouble()
|
||||
&& e < (if (currentNode.type in verticallyPreciseNodeTypes && (mob.isUnderWater || pather.isFlying())) maxDistanceToWaypoint else 1.0).toDouble()
|
||||
&& e < (if (currentNode.type in verticallyPreciseNodeTypes) maxDistanceToWaypoint else 1.0).toDouble()
|
||||
|
||||
// Corner cutting is commented out because it makes pokemon and NPCs 'cut' the corner and fall into water or lava
|
||||
if (closeEnough) {// || mob.navigation.canCutCorner(path!!.nextNode.type) && shouldTargetNextNodeInDirection(vec3d)) {
|
||||
@@ -228,25 +229,6 @@ class OmniPathNavigation(val world: Level, val entity: Mob) : GroundPathNavigati
|
||||
return true
|
||||
}
|
||||
}
|
||||
if (mob.canBreatheUnderwater()) {
|
||||
val blockGetter: BlockGetter = level
|
||||
if (blockGetter.getFluidState(pos).`is`(FluidTags.WATER)) {
|
||||
val blockPos = pos.below()
|
||||
return level.getBlockState(blockPos).isSolidRender(this.level, blockPos)
|
||||
}
|
||||
}
|
||||
if (pather.canWalkOnWater()) {
|
||||
val blockGetter: BlockGetter = level
|
||||
if (blockGetter.getFluidState(pos.below()).`is`(FluidTags.WATER)) {
|
||||
return !level.getBlockState(pos).isSolidRender(this.level, pos)
|
||||
}
|
||||
}
|
||||
if (pather.canWalkOnLava()) {
|
||||
val blockGetter: BlockGetter = level
|
||||
if (blockGetter.getFluidState(pos.below()).`is`(FluidTags.LAVA)) {
|
||||
return !level.getBlockState(pos).isSolidRender(this.level, pos)
|
||||
}
|
||||
}
|
||||
if (pather.canFly()) {
|
||||
return this.level.getBlockState(pos).isAir || super.isStableDestination(pos)
|
||||
// Note the below is what is used by default for minecraft fliers
|
||||
@@ -264,7 +246,7 @@ class OmniPathNavigation(val world: Level, val entity: Mob) : GroundPathNavigati
|
||||
// If we can fly and we're airborne, return the current Y position
|
||||
return vec.y
|
||||
}
|
||||
return if ((canFloat()) && blockGetter.getFluidState(blockPos).`is`(FluidTags.WATER)) vec.y + 0.5 else super.getGroundY(vec)
|
||||
return if ((canFloat()) && blockGetter.getFluidState(blockPos).`is`(FluidTags.WATER)) vec.y + 0.5 else WalkNodeEvaluator.getFloorLevel(blockGetter, blockPos)
|
||||
}
|
||||
|
||||
override fun createPath(entity: Entity, distance: Int): Path? {
|
||||
|
||||
@@ -20,8 +20,7 @@ class StayAfloatTask(private val chance: Float = 0F) : Behavior<PathfinderMob>(
|
||||
ImmutableMap.of(CobblemonMemories.POKEMON_BATTLE, MemoryStatus.VALUE_ABSENT) // Prevents Illusion Pokemon from bouncing in the water when disguised as swimmers.
|
||||
) {
|
||||
override fun checkExtraStartConditions(world: ServerLevel, entity: PathfinderMob): Boolean {
|
||||
return entity.isInWater && (entity.getFluidHeight(FluidTags.WATER) > entity.fluidJumpThreshold) ||
|
||||
(entity.isInLava && !entity.fireImmune())
|
||||
return entity.isInWater && (entity.getFluidHeight(FluidTags.WATER) > entity.fluidJumpThreshold) || entity.isInLava
|
||||
}
|
||||
|
||||
override fun canStillUse(world: ServerLevel, entity: PathfinderMob, l: Long): Boolean {
|
||||
|
||||
@@ -696,18 +696,10 @@ class NPCEntity(world: Level) : AgeableMob(CobblemonEntities.NPC, world), Npc, P
|
||||
return false
|
||||
}
|
||||
|
||||
override fun canWalkOnLava(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun canSwimUnderFluid(fluidState: FluidState): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun canWalkOnWater(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
override fun canFly(): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -73,7 +73,6 @@ import com.cobblemon.mod.common.battles.BattleBuilder
|
||||
import com.cobblemon.mod.common.battles.BattleRegistry
|
||||
import com.cobblemon.mod.common.battles.SuccessfulBattleStart
|
||||
import com.cobblemon.mod.common.block.entity.PokemonPastureBlockEntity
|
||||
import com.cobblemon.mod.common.client.MountedCameraTypeHandler
|
||||
import com.cobblemon.mod.common.client.entity.PokemonClientDelegate
|
||||
import com.cobblemon.mod.common.entity.BehaviourEditingTracker
|
||||
import com.cobblemon.mod.common.entity.EntityCallbacks
|
||||
@@ -217,7 +216,6 @@ open class PokemonEntity(
|
||||
@JvmStatic val EVOLUTION_STARTED = SynchedEntityData.defineId(PokemonEntity::class.java, EntityDataSerializers.BOOLEAN)
|
||||
@JvmStatic var SHOWN_HELD_ITEM = SynchedEntityData.defineId(PokemonEntity::class.java, EntityDataSerializers.ITEM_STACK)
|
||||
@JvmStatic var RIDE_BOOSTS = SynchedEntityData.defineId(PokemonEntity::class.java, RideBoostsDataSerializer)
|
||||
@JvmStatic var RIDE_STAMINA = SynchedEntityData.defineId(PokemonEntity::class.java, EntityDataSerializers.FLOAT)
|
||||
|
||||
const val BATTLE_LOCK = "battle"
|
||||
const val EVOLUTION_LOCK = "evolving"
|
||||
@@ -462,7 +460,6 @@ open class PokemonEntity(
|
||||
builder.define(EVOLUTION_STARTED, false)
|
||||
builder.define(SHOWN_HELD_ITEM, ItemStack.EMPTY)
|
||||
builder.define(RIDE_BOOSTS, emptyMap())
|
||||
builder.define(RIDE_STAMINA, 1F)
|
||||
}
|
||||
|
||||
override fun onSyncedDataUpdated(data: EntityDataAccessor<*>) {
|
||||
@@ -540,12 +537,8 @@ open class PokemonEntity(
|
||||
if (passengerIndex != -1) {
|
||||
occupiedSeats[passengerIndex] = null
|
||||
}
|
||||
if (level().isClientSide) {
|
||||
MountedCameraTypeHandler.handleDismount(passenger, this)
|
||||
}
|
||||
super.removePassenger(passenger)
|
||||
if (passengers.isEmpty()) {
|
||||
ifRidingAvailable { _, _, state -> pokemon.rideStamina = state.stamina.get() }
|
||||
ridingController?.context?.state?.reset()
|
||||
ridingAnimationData.clear()
|
||||
}
|
||||
@@ -1462,7 +1455,7 @@ open class PokemonEntity(
|
||||
fun tryRidingPokemon(player: ServerPlayer): Boolean {
|
||||
val event = RidePokemonEvent.Pre(player, this)
|
||||
CobblemonEvents.RIDE_EVENT_PRE.post(event)
|
||||
if (!event.isCanceled) {
|
||||
if(!event.isCanceled) {
|
||||
player.startRiding(this)
|
||||
CobblemonEvents.RIDE_EVENT_POST.post(RidePokemonEvent.Post(player, this))
|
||||
return true
|
||||
@@ -2073,7 +2066,7 @@ open class PokemonEntity(
|
||||
}
|
||||
|
||||
// Takes in a requested stat type with a base minimum and base maximum and returns the interpolated
|
||||
// stat based on the boost of that Pokémon's stat
|
||||
// stat based on the boost of that pokemons stat
|
||||
fun getRideStat(rideStat: RidingStat, style: RidingStyle, baseMin: Double, baseMax: Double): Double {
|
||||
if (rideStatOverrides[style] != null && rideStatOverrides[style]!![rideStat] != null) {
|
||||
return (((baseMax - baseMin) / 100) * rideStatOverrides[style]!![rideStat]!!) + baseMin
|
||||
@@ -2105,37 +2098,16 @@ open class PokemonEntity(
|
||||
|
||||
public override fun addPassenger(passenger: Entity) {
|
||||
if (passenger is ServerPlayer) {
|
||||
// Recall all the rest of the player's party pokes
|
||||
passenger.party()
|
||||
.mapNotNull { it.entity }
|
||||
.filter { it != this }
|
||||
.forEach { it.recallWithAnimation() }
|
||||
|
||||
// Driver is hopping on, figure out the stamina situation
|
||||
if (passengers.isEmpty()) {
|
||||
CobblemonEvents.RIDE_EVENT_APPLY_STAMINA.post(
|
||||
RidePokemonEvent.ApplyStamina(
|
||||
player = passenger,
|
||||
pokemon = this,
|
||||
rideStamina = if (Cobblemon.config.infiniteRideStamina) -1F else entityData.get(RIDE_STAMINA)
|
||||
),
|
||||
then = { event -> entityData.set(RIDE_STAMINA, event.rideStamina) }
|
||||
)
|
||||
}
|
||||
} else if (level().isClientSide) {
|
||||
MountedCameraTypeHandler.handleMount(passenger, this)
|
||||
}
|
||||
val passengerIndex = occupiedSeats.indexOfFirst { it == null }
|
||||
if (passengerIndex != -1) {
|
||||
occupiedSeats[passengerIndex] = passenger
|
||||
}
|
||||
super.addPassenger(passenger)
|
||||
if (passengers.size == 1) {
|
||||
// Someone just started riding, fill in the stamina value! Gets run from both sides.
|
||||
ifRidingAvailable { _, _, state ->
|
||||
state.stamina.set(entityData.get(RIDE_STAMINA))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getIsJumping() = jumping
|
||||
@@ -2165,9 +2137,6 @@ open class PokemonEntity(
|
||||
super.tickRidden(driver, movementInput)
|
||||
ifRidingAvailable { behaviour, settings, state ->
|
||||
behaviour.tick(settings, state, this, driver, movementInput)
|
||||
if (entityData.get(RIDE_STAMINA) == -1F) {
|
||||
state.stamina.set(1F, forced = true)
|
||||
}
|
||||
|
||||
if (!this.level().isClientSide) {
|
||||
val pose = behaviour.pose(settings, state, this)
|
||||
@@ -2427,10 +2396,8 @@ open class PokemonEntity(
|
||||
|
||||
override fun canWalk() = exposedForm.behaviour.moving.walk.canWalk
|
||||
override fun canSwimInWater() = exposedForm.behaviour.moving.swim.canSwimInWater
|
||||
override fun canWalkOnWater() = exposedForm.behaviour.moving.swim.canWalkOnWater
|
||||
override fun canFly() = exposedForm.behaviour.moving.fly.canFly
|
||||
override fun canSwimInLava() = exposedForm.behaviour.moving.swim.canSwimInLava
|
||||
override fun canWalkOnLava() = exposedForm.behaviour.moving.swim.canWalkOnLava
|
||||
override fun entityOnGround() = onGround()
|
||||
|
||||
override fun canSwimUnderFluid(fluidState: FluidState): Boolean {
|
||||
|
||||
+3
-8
@@ -76,14 +76,12 @@ class PokemonServerDelegate : PokemonSideDelegate {
|
||||
val moving = pokemon.form.behaviour.moving
|
||||
entity.setPathfindingMalus(PathType.LAVA, if (moving.swim.canSwimInLava) 12F else -1F)
|
||||
entity.setPathfindingMalus(PathType.WATER, if (moving.swim.canSwimInWater) 12F else -1F)
|
||||
entity.setPathfindingMalus(PathType.WATER_BORDER, if (moving.swim.canSwimInWater || moving.walk.avoidsLand || moving.swim.canBreatheUnderwater) 6F else -1F)
|
||||
entity.setPathfindingMalus(PathType.WATER_BORDER, if (moving.swim.canSwimInWater) 6F else -1F)
|
||||
if (moving.swim.canBreatheUnderwater) {
|
||||
// Must have a malus of zero to be a valid wander target
|
||||
entity.setPathfindingMalus(PathType.WATER, 0F)
|
||||
entity.setPathfindingMalus(PathType.WATER, if (moving.walk.avoidsLand) 0F else 4F)
|
||||
}
|
||||
if (moving.swim.canBreatheUnderlava) {
|
||||
// Must have a malus of zero to be a valid wander target
|
||||
entity.setPathfindingMalus(PathType.LAVA, if (moving.swim.canSwimInLava) 0F else -1F)
|
||||
entity.setPathfindingMalus(PathType.LAVA, if (moving.swim.canSwimInLava) 4F else -1F)
|
||||
}
|
||||
if (moving.walk.avoidsLand) {
|
||||
entity.setPathfindingMalus(PathType.WALKABLE, 12F)
|
||||
@@ -235,9 +233,6 @@ class PokemonServerDelegate : PokemonSideDelegate {
|
||||
|
||||
entity.entityData.set(PokemonEntity.FRIENDSHIP, entity.pokemon.friendship)
|
||||
entity.entityData.set(PokemonEntity.CAUGHT_BALL, trackedBall)
|
||||
if (entity.pokemon.rideStamina != entity.entityData.get(PokemonEntity.RIDE_STAMINA) && entity.passengers.isEmpty()) {
|
||||
entity.entityData.set(PokemonEntity.RIDE_STAMINA, entity.pokemon.rideStamina)
|
||||
}
|
||||
|
||||
val currentRideBoosts = entity.entityData.get(PokemonEntity.RIDE_BOOSTS)
|
||||
val newRideBoosts = entity.pokemon.getRideBoosts()
|
||||
|
||||
@@ -80,7 +80,6 @@ object CallbackHandler {
|
||||
CobblemonEvents.TRADE_EVENT_PRE.subscribe { CobblemonCallbacks.run(cobblemonResource("trade_event_pre"), it.context, it.functions) }
|
||||
CobblemonEvents.TRADE_EVENT_POST.subscribe { CobblemonCallbacks.run(cobblemonResource("trade_event_post"), it.context) }
|
||||
CobblemonEvents.RIDE_EVENT_PRE.subscribe { CobblemonCallbacks.run(cobblemonResource("ride_event_pre"), it.context, it.functions) }
|
||||
CobblemonEvents.RIDE_EVENT_APPLY_STAMINA.subscribe { CobblemonCallbacks.run(cobblemonResource("ride_event_apply_stamina"), it.context, it.functions) }
|
||||
CobblemonEvents.RIDE_EVENT_POST.subscribe { CobblemonCallbacks.run(cobblemonResource("ride_event_post"), it.context) }
|
||||
CobblemonEvents.WALLPAPER_UNLOCKED_EVENT.subscribe { CobblemonCallbacks.run(cobblemonResource("wallpaper_unlocked"), it.context, it.functions) }
|
||||
CobblemonEvents.CHANGE_PC_BOX_WALLPAPER_EVENT_PRE.subscribe { CobblemonCallbacks.run(cobblemonResource("change_pc_box_wallpaper_pre"), it.context, it.functions) }
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.item
|
||||
|
||||
import com.cobblemon.mod.common.api.item.PokemonSelectingItem
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.sounds.SoundEvent
|
||||
@@ -29,37 +30,35 @@ class RegionalFoodItem(properties: Properties) : Item(properties), PokemonSelect
|
||||
override fun use(world: Level, player: Player, hand: InteractionHand): InteractionResultHolder<ItemStack> {
|
||||
val stack = player.getItemInHand(hand)
|
||||
|
||||
if (player !is ServerPlayer) {
|
||||
return InteractionResultHolder.pass(stack);
|
||||
}
|
||||
|
||||
// Prioritizes healing pokémon with the item
|
||||
val superInteractionResult = super<PokemonSelectingItem>.use(player, stack)
|
||||
if (superInteractionResult.result != InteractionResult.PASS) {
|
||||
return superInteractionResult
|
||||
}
|
||||
|
||||
// Otherwise allow eating normally if player needs food OR in creative
|
||||
// Allow eating normally if player needs food OR in creative
|
||||
if (player.foodData.needsFood() || player.isCreative) {
|
||||
player.startUsingItem(hand)
|
||||
return InteractionResultHolder.consume(stack)
|
||||
}
|
||||
|
||||
return InteractionResultHolder.pass(stack)
|
||||
return InteractionResultHolder.fail(stack)
|
||||
}
|
||||
|
||||
override fun applyToPokemon(
|
||||
player: ServerPlayer,
|
||||
stack: ItemStack,
|
||||
pokemon: Pokemon
|
||||
): InteractionResultHolder<ItemStack> {
|
||||
override fun interactLivingEntity(stack: ItemStack, player: Player, target: LivingEntity, hand: InteractionHand): InteractionResult {
|
||||
if (player.level().isClientSide) return InteractionResult.PASS
|
||||
|
||||
if (player is ServerPlayer && target is PokemonEntity) {
|
||||
val pokemon = target.pokemon
|
||||
if (pokemon.status != null) {
|
||||
return InteractionResult.SUCCESS
|
||||
}
|
||||
}
|
||||
|
||||
return InteractionResult.PASS
|
||||
}
|
||||
|
||||
override fun applyToPokemon(player: ServerPlayer, stack: ItemStack, pokemon: Pokemon): InteractionResultHolder<ItemStack> {
|
||||
if (pokemon.status != null) {
|
||||
pokemon.status = null
|
||||
pokemon.entity?.playSound(SoundEvents.GENERIC_EAT, 1F, 1F)
|
||||
stack.consume(1, player)
|
||||
return InteractionResultHolder.success(stack)
|
||||
}
|
||||
|
||||
return InteractionResultHolder.fail(stack)
|
||||
}
|
||||
|
||||
|
||||
-93
@@ -1,93 +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.data
|
||||
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.types.air.BirdSettings
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.types.air.GliderSettings
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.types.air.HelicopterSettings
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.types.air.HoverSettings
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.types.air.JetSettings
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.types.air.RocketSettings
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.types.land.HorseSettings
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.types.land.MinekartSettings
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.types.land.VehicleSettings
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.types.liquid.BoatSettings
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.types.liquid.BurstSettings
|
||||
import com.cobblemon.mod.common.api.riding.behaviour.types.liquid.DolphinSettings
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
|
||||
/**
|
||||
* Synchronizes the [com.cobblemon.mod.common.CobblemonRideSettings] registry.
|
||||
*/
|
||||
class RideSettingsSyncPacket(
|
||||
val bird: BirdSettings,
|
||||
val glider: GliderSettings,
|
||||
val helicopter: HelicopterSettings,
|
||||
val hover: HoverSettings,
|
||||
val jet: JetSettings,
|
||||
val rocket: RocketSettings,
|
||||
val horse: HorseSettings,
|
||||
val minekart: MinekartSettings,
|
||||
val vehicle: VehicleSettings,
|
||||
val boat: BoatSettings,
|
||||
val burst: BurstSettings,
|
||||
val dolphin: DolphinSettings
|
||||
) : NetworkPacket<RideSettingsSyncPacket> {
|
||||
override val id = ID
|
||||
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {
|
||||
bird.encode(buffer)
|
||||
glider.encode(buffer)
|
||||
helicopter.encode(buffer)
|
||||
hover.encode(buffer)
|
||||
jet.encode(buffer)
|
||||
rocket.encode(buffer)
|
||||
horse.encode(buffer)
|
||||
minekart.encode(buffer)
|
||||
vehicle.encode(buffer)
|
||||
boat.encode(buffer)
|
||||
burst.encode(buffer)
|
||||
dolphin.encode(buffer)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val ID = cobblemonResource("mechanics_sync")
|
||||
fun decode(buffer: RegistryFriendlyByteBuf): RideSettingsSyncPacket {
|
||||
return RideSettingsSyncPacket(
|
||||
bird = BirdSettings(),
|
||||
glider = GliderSettings(),
|
||||
helicopter = HelicopterSettings(),
|
||||
hover = HoverSettings(),
|
||||
jet = JetSettings(),
|
||||
rocket = RocketSettings(),
|
||||
horse = HorseSettings(),
|
||||
minekart = MinekartSettings(),
|
||||
vehicle = VehicleSettings(),
|
||||
boat = BoatSettings(),
|
||||
burst = BurstSettings(),
|
||||
dolphin = DolphinSettings()
|
||||
).apply {
|
||||
bird.decode(buffer)
|
||||
glider.decode(buffer)
|
||||
helicopter.decode(buffer)
|
||||
hover.decode(buffer)
|
||||
jet.decode(buffer)
|
||||
rocket.decode(buffer)
|
||||
horse.decode(buffer)
|
||||
minekart.decode(buffer)
|
||||
vehicle.decode(buffer)
|
||||
boat.decode(buffer)
|
||||
burst.decode(buffer)
|
||||
dolphin.decode(buffer)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.net.messages.client.data
|
||||
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
|
||||
internal class UnlockReloadPacket : NetworkPacket<UnlockReloadPacket> {
|
||||
companion object {
|
||||
val ID = cobblemonResource("unlock_reload")
|
||||
|
||||
fun decode(buffer: RegistryFriendlyByteBuf) = UnlockReloadPacket()
|
||||
}
|
||||
|
||||
override val id = ID
|
||||
override fun encode(buffer: RegistryFriendlyByteBuf) {}
|
||||
}
|
||||
-39
@@ -1,39 +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.pokemon.update
|
||||
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
|
||||
/**
|
||||
* Packet sent when the tracked stamina on Pokémon is updated. This is not the value that's
|
||||
* actively controlling riding but rather the tracking property which is put into the riding
|
||||
* state when the Pokémon is mounted.
|
||||
*/
|
||||
class RideStaminaUpdatePacket(pokemon: () -> Pokemon?, value: Float) : SingleUpdatePacket<Float, RideStaminaUpdatePacket>(pokemon, value) {
|
||||
companion object {
|
||||
val ID = com.cobblemon.mod.common.util.cobblemonResource("ride_stamina_update")
|
||||
fun decode(buffer: RegistryFriendlyByteBuf): RideStaminaUpdatePacket {
|
||||
val pokemon = decodePokemon(buffer)
|
||||
val value = buffer.readFloat()
|
||||
return RideStaminaUpdatePacket(pokemon, value)
|
||||
}
|
||||
}
|
||||
|
||||
override fun set(pokemon: Pokemon, value: Float) {
|
||||
Cobblemon.LOGGER.info("Updating client with $value")
|
||||
pokemon.rideStamina = value
|
||||
}
|
||||
|
||||
override val id = ID
|
||||
override fun encodeValue(buffer: RegistryFriendlyByteBuf) {
|
||||
buffer.writeFloat(this.value)
|
||||
}
|
||||
}
|
||||
+33
-77
@@ -17,22 +17,14 @@ import com.cobblemon.mod.common.entity.PlatformType
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.pokemon.Gender
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.readEnumConstant
|
||||
import com.cobblemon.mod.common.util.readIdentifier
|
||||
import com.cobblemon.mod.common.util.readString
|
||||
import com.cobblemon.mod.common.util.readText
|
||||
import com.cobblemon.mod.common.util.writeEnumConstant
|
||||
import com.cobblemon.mod.common.util.writeIdentifier
|
||||
import com.cobblemon.mod.common.util.writeString
|
||||
import com.cobblemon.mod.common.util.writeText
|
||||
import java.util.UUID
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import net.minecraft.client.multiplayer.ClientLevel
|
||||
import java.util.UUID
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.network.RegistryFriendlyByteBuf
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import net.minecraft.network.protocol.game.ClientboundAddEntityPacket
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.entity.Entity
|
||||
|
||||
class SpawnPokemonPacket(
|
||||
var ownerId: UUID?,
|
||||
@@ -60,40 +52,38 @@ class SpawnPokemonPacket(
|
||||
var passengers: IntArray,
|
||||
var tickSpawned: Int,
|
||||
var rideBoosts: Map<RidingStat, Float>,
|
||||
var rideStamina: Float,
|
||||
vanillaSpawnPacket: ClientboundAddEntityPacket,
|
||||
) : SpawnExtraDataEntityPacket<SpawnPokemonPacket, PokemonEntity>(vanillaSpawnPacket) {
|
||||
|
||||
override val id: ResourceLocation = ID
|
||||
|
||||
constructor(entity: PokemonEntity, vanillaSpawnPacket: ClientboundAddEntityPacket) : this(
|
||||
entity.ownerUUID,
|
||||
entity.pokemon.uuid,
|
||||
entity.pokemon.scaleModifier,
|
||||
entity.exposedSpecies.resourceIdentifier,
|
||||
entity.pokemon.gender,
|
||||
entity.pokemon.shiny,
|
||||
entity.exposedForm.formOnlyShowdownId(),
|
||||
entity.exposedAspects,
|
||||
entity.battleId,
|
||||
entity.phasingTargetId,
|
||||
entity.beamMode.toByte(),
|
||||
entity.platform,
|
||||
entity.pokemon.nickname,
|
||||
entity.pokemon.activeMark?.identifier,
|
||||
if (Cobblemon.config.displayEntityLevelLabel) entity.entityData.get(PokemonEntity.LABEL_LEVEL) else -1,
|
||||
entity.entityData.get(PokemonEntity.POSE_TYPE),
|
||||
entity.entityData.get(PokemonEntity.UNBATTLEABLE),
|
||||
entity.entityData.get(PokemonEntity.HIDE_LABEL),
|
||||
entity.exposedBall.name,
|
||||
entity.entityData.get(PokemonEntity.SPAWN_DIRECTION),
|
||||
entity.entityData.get(PokemonEntity.FRIENDSHIP),
|
||||
entity.entityData.get(PokemonEntity.FREEZE_FRAME),
|
||||
entity.passengers.map { it.id }.toIntArray(),
|
||||
entity.tickCount,
|
||||
entity.entityData.get(PokemonEntity.RIDE_BOOSTS),
|
||||
entity.entityData.get(PokemonEntity.RIDE_STAMINA),
|
||||
vanillaSpawnPacket
|
||||
entity.ownerUUID,
|
||||
entity.pokemon.uuid,
|
||||
entity.pokemon.scaleModifier,
|
||||
entity.exposedSpecies.resourceIdentifier,
|
||||
entity.pokemon.gender,
|
||||
entity.pokemon.shiny,
|
||||
entity.exposedForm.formOnlyShowdownId(),
|
||||
entity.exposedAspects,
|
||||
entity.battleId,
|
||||
entity.phasingTargetId,
|
||||
entity.beamMode.toByte(),
|
||||
entity.platform,
|
||||
entity.pokemon.nickname,
|
||||
entity.pokemon.activeMark?.identifier,
|
||||
if (Cobblemon.config.displayEntityLevelLabel) entity.entityData.get(PokemonEntity.LABEL_LEVEL) else -1,
|
||||
entity.entityData.get(PokemonEntity.POSE_TYPE),
|
||||
entity.entityData.get(PokemonEntity.UNBATTLEABLE),
|
||||
entity.entityData.get(PokemonEntity.HIDE_LABEL),
|
||||
entity.exposedBall.name,
|
||||
entity.entityData.get(PokemonEntity.SPAWN_DIRECTION),
|
||||
entity.entityData.get(PokemonEntity.FRIENDSHIP),
|
||||
entity.entityData.get(PokemonEntity.FREEZE_FRAME),
|
||||
entity.passengers.map { it.id }.toIntArray(),
|
||||
entity.tickCount,
|
||||
entity.entityData.get(PokemonEntity.RIDE_BOOSTS),
|
||||
vanillaSpawnPacket
|
||||
)
|
||||
|
||||
override fun encodeEntityData(buffer: RegistryFriendlyByteBuf) {
|
||||
@@ -126,7 +116,6 @@ class SpawnPokemonPacket(
|
||||
{ _, stat -> buffer.writeEnumConstant(stat) },
|
||||
{ _, value -> buffer.writeFloat(value) }
|
||||
)
|
||||
buffer.writeFloat(rideStamina)
|
||||
}
|
||||
|
||||
override fun applyData(entity: PokemonEntity, level: ClientLevel) {
|
||||
@@ -134,16 +123,13 @@ class SpawnPokemonPacket(
|
||||
entity.pokemon.apply {
|
||||
uuid = this@SpawnPokemonPacket.pokemonUUID
|
||||
scaleModifier = this@SpawnPokemonPacket.scaleModifier
|
||||
species =
|
||||
this@SpawnPokemonPacket.speciesId.let { PokemonSpecies.getByIdentifier(it) ?: PokemonSpecies.random() }
|
||||
species = this@SpawnPokemonPacket.speciesId.let { PokemonSpecies.getByIdentifier(it) ?: PokemonSpecies.random() }
|
||||
gender = this@SpawnPokemonPacket.gender
|
||||
shiny = this@SpawnPokemonPacket.shiny
|
||||
form =
|
||||
this@SpawnPokemonPacket.formName.let { formName -> species.forms.find { it.formOnlyShowdownId() == formName } }
|
||||
?: species.standardForm
|
||||
form = this@SpawnPokemonPacket.formName.let { formName -> species.forms.find { it.formOnlyShowdownId() == formName }} ?: species.standardForm
|
||||
forcedAspects = this@SpawnPokemonPacket.aspects
|
||||
nickname = this@SpawnPokemonPacket.nickname
|
||||
this@SpawnPokemonPacket.mark?.let { activeMark = Marks.getByIdentifier(it) }
|
||||
this@SpawnPokemonPacket.mark?.let {activeMark = Marks.getByIdentifier(it) }
|
||||
PokeBalls.getPokeBall(this@SpawnPokemonPacket.caughtBall)?.let { caughtBall = it }
|
||||
}
|
||||
entity.phasingTargetId = this.phasingTargetId
|
||||
@@ -160,7 +146,6 @@ class SpawnPokemonPacket(
|
||||
entity.entityData.set(PokemonEntity.FRIENDSHIP, friendship)
|
||||
entity.entityData.set(PokemonEntity.FREEZE_FRAME, freezeFrame)
|
||||
entity.entityData.set(PokemonEntity.RIDE_BOOSTS, rideBoosts)
|
||||
entity.entityData.set(PokemonEntity.RIDE_STAMINA, rideStamina)
|
||||
|
||||
entity.ejectPassengers()
|
||||
passengers.forEach {
|
||||
@@ -204,38 +189,9 @@ class SpawnPokemonPacket(
|
||||
{ buffer.readEnumConstant(RidingStat::class.java) },
|
||||
{ buffer.readFloat() }
|
||||
)
|
||||
val rideStamina = buffer.readFloat()
|
||||
val vanillaPacket = decodeVanillaPacket(buffer)
|
||||
|
||||
return SpawnPokemonPacket(
|
||||
ownerId,
|
||||
pokemonUUID,
|
||||
scaleModifier,
|
||||
speciesId,
|
||||
gender,
|
||||
shiny,
|
||||
formName,
|
||||
aspects,
|
||||
battleId,
|
||||
phasingTargetId,
|
||||
beamModeEmitter,
|
||||
platform,
|
||||
nickname,
|
||||
mark,
|
||||
labelLevel,
|
||||
poseType,
|
||||
unbattlable,
|
||||
hideLabel,
|
||||
caughtBall,
|
||||
spawnAngle,
|
||||
friendship,
|
||||
freezeFrame,
|
||||
passengers,
|
||||
tickSpawned,
|
||||
rideBoosts,
|
||||
rideStamina,
|
||||
vanillaPacket
|
||||
)
|
||||
return SpawnPokemonPacket(ownerId, pokemonUUID, scaleModifier, speciesId, gender, shiny, formName, aspects, battleId, phasingTargetId, beamModeEmitter, platform, nickname, mark, labelLevel, poseType, unbattlable, hideLabel, caughtBall, spawnAngle, friendship, freezeFrame, passengers, tickSpawned, rideBoosts, vanillaPacket)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -58,7 +58,6 @@ import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||
import com.cobblemon.mod.common.api.properties.CustomPokemonProperty
|
||||
import com.cobblemon.mod.common.api.reactive.SettableObservable
|
||||
import com.cobblemon.mod.common.api.riding.RidingProperties
|
||||
import com.cobblemon.mod.common.api.riding.RidingStyle
|
||||
import com.cobblemon.mod.common.api.riding.stats.RidingStat
|
||||
import com.cobblemon.mod.common.api.scheduling.afterOnServer
|
||||
import com.cobblemon.mod.common.api.storage.StoreCoordinates
|
||||
@@ -358,29 +357,16 @@ open class Pokemon : ShowdownIdentifiable {
|
||||
|
||||
var currentFullness = 0
|
||||
set(value) {
|
||||
val clamped = value.coerceIn(0, getMaxFullness())
|
||||
if (field == clamped) return
|
||||
|
||||
FULLNESS_UPDATED.post(FullnessUpdatedEvent(this, clamped)) {
|
||||
if (value < 0) {
|
||||
field = 0
|
||||
return
|
||||
}
|
||||
FULLNESS_UPDATED.post(FullnessUpdatedEvent(this, value)) {
|
||||
field = it.newFullness
|
||||
onChange(FullnessUpdatePacket({ this }, it.newFullness))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Just a persistence version of the ride stamina used to hold onto
|
||||
* it between one ride and another. Only applied at the moment of
|
||||
* mounting the Pokémon.
|
||||
*/
|
||||
var rideStamina = 1F
|
||||
set(value) {
|
||||
val newValue = value.coerceIn(0F, 1F)
|
||||
if (newValue != field) {
|
||||
field = newValue
|
||||
onChange(RideStaminaUpdatePacket({ this }, newValue))
|
||||
}
|
||||
}
|
||||
|
||||
var interactionCooldowns: MutableMap<ResourceLocation, Int> = mutableMapOf()
|
||||
|
||||
var state: PokemonState = InactivePokemonState()
|
||||
@@ -1835,10 +1821,13 @@ open class Pokemon : ShowdownIdentifiable {
|
||||
moveSet.update()
|
||||
}
|
||||
|
||||
fun getMaxRideBoost(stat: RidingStat): Float {
|
||||
val behaviours = form.riding.behaviours ?: return 0F
|
||||
// Get the widest range for this stat, max - min, since that's how far it can be boosted in theory.
|
||||
return behaviours.values.maxOfOrNull { it.stats[stat]?.let { it.last - it.first }?.toFloat() ?: 0F } ?: 0F
|
||||
/**
|
||||
* Gets the largest conceivable boost that can be granted to a stat. This is effectively the widest range
|
||||
* from min to max of this stat for any of the styles. For example, if ACCELERATION is from 10 to 40 in one
|
||||
* style and 20 to 60 in another, the max ride boost is 40.
|
||||
*/
|
||||
fun getMaxRideBoost(stat: RidingStat): Int {
|
||||
return form.riding.behaviours?.maxOf { it.value.stats[stat]?.let { it.last - it.first } ?: 0 } ?: 0
|
||||
}
|
||||
|
||||
fun getRideBoost(stat: RidingStat): Float {
|
||||
@@ -1849,36 +1838,31 @@ open class Pokemon : ShowdownIdentifiable {
|
||||
return rideBoosts.toMap()
|
||||
}
|
||||
|
||||
fun getRideStat(style: RidingStyle, stat: RidingStat): Float {
|
||||
form.riding.behaviours?.let {
|
||||
return it[style]?.calculate(stat, getRideBoost(stat)) ?: 0F
|
||||
}
|
||||
return 0F
|
||||
}
|
||||
|
||||
fun canAddRideBoost(stat: RidingStat): Boolean {
|
||||
val max = getMaxRideBoost(stat)
|
||||
val current = rideBoosts[stat] ?: 0F
|
||||
return current < getMaxRideBoost(stat)
|
||||
return current < max
|
||||
}
|
||||
|
||||
fun addRideBoost(stat: RidingStat, boostAmount: Float): Boolean {
|
||||
fun addRideBoost(stat: RidingStat, boost: Float): Boolean {
|
||||
if (!canAddRideBoost(stat)) {
|
||||
return false
|
||||
}
|
||||
val max = getMaxRideBoost(stat)
|
||||
rideBoosts[stat] = (getRideBoost(stat) + boostAmount).coerceAtMost(max)
|
||||
rideBoosts[stat] = (getRideBoost(stat) + boost).coerceIn(0F, max.toFloat())
|
||||
onChange(RideBoostsUpdatePacket({ this }, rideBoosts))
|
||||
return true
|
||||
}
|
||||
|
||||
fun setRideBoost(stat: RidingStat, boost: Float) {
|
||||
rideBoosts[stat] = boost.coerceIn(0F, getMaxRideBoost(stat))
|
||||
val max = getMaxRideBoost(stat)
|
||||
rideBoosts[stat] = boost.coerceIn(0F, max.toFloat())
|
||||
onChange(RideBoostsUpdatePacket({ this }, rideBoosts))
|
||||
}
|
||||
|
||||
fun setRideBoosts(boosts: Map<RidingStat, Float>) {
|
||||
rideBoosts.clear()
|
||||
rideBoosts.putAll(boosts.mapValues { it.value.coerceIn(0F, getMaxRideBoost(it.key)) })
|
||||
rideBoosts.putAll(boosts.mapValues { it.value.coerceIn(0F, getMaxRideBoost(it.key).toFloat()) })
|
||||
onChange(RideBoostsUpdatePacket({ this }, rideBoosts))
|
||||
}
|
||||
|
||||
@@ -1898,7 +1882,7 @@ open class Pokemon : ShowdownIdentifiable {
|
||||
if (result.experienceAdded <= 0) {
|
||||
return result
|
||||
}
|
||||
player.sendSystemMessage(lang("experience.gained", getDisplayName(), result.experienceAdded), true)
|
||||
player.sendSystemMessage(lang("experience.gained", getDisplayName(), xp), true)
|
||||
if (result.oldLevel != result.newLevel) {
|
||||
player.sendSystemMessage(lang("experience.level_up", getDisplayName(), result.newLevel))
|
||||
val repeats = result.newLevel - result.oldLevel
|
||||
|
||||
@@ -417,11 +417,7 @@ class OmniPathNodeMaker : NodeEvaluator() {
|
||||
PathType.FENCE
|
||||
}
|
||||
} else if (isWater && !canSwimInWater() && canBreatheUnderFluid && blockState.isPathfindable(PathComputationType.LAND) ) {
|
||||
if (pfContext.getPathTypeFromState(pos.x, pos.y - 1, pos.z) == PathType.BLOCKED) {
|
||||
PathType.WALKABLE
|
||||
} else {
|
||||
PathType.OPEN
|
||||
}
|
||||
PathType.OPEN
|
||||
} else if (isLava && canSwimInLava()) {
|
||||
PathType.LAVA
|
||||
} else if (isWater) {
|
||||
@@ -444,13 +440,12 @@ class OmniPathNodeMaker : NodeEvaluator() {
|
||||
|
||||
if (figuredNode == PathType.OPEN && pos.y >= pfContext.level().getMinBuildHeight() + 1) {
|
||||
val var10000: PathType = when (pfContext.getPathTypeFromState(pos.x, pos.y - 1, pos.z)) {
|
||||
PathType.OPEN, PathType.LAVA, PathType.WALKABLE -> PathType.OPEN
|
||||
PathType.OPEN, PathType.WATER, PathType.LAVA, PathType.WALKABLE -> PathType.OPEN
|
||||
PathType.DAMAGE_OTHER -> PathType.DAMAGE_OTHER
|
||||
PathType.STICKY_HONEY -> PathType.STICKY_HONEY
|
||||
PathType.POWDER_SNOW -> PathType.DANGER_POWDER_SNOW
|
||||
PathType.DAMAGE_CAUTIOUS -> PathType.DAMAGE_CAUTIOUS
|
||||
PathType.TRAPDOOR -> PathType.DANGER_TRAPDOOR
|
||||
PathType.WATER -> if (canWalkOnWater()) PathType.WALKABLE else PathType.OPEN
|
||||
PathType.FENCE -> {
|
||||
if (canFly())
|
||||
PathType.BLOCKED
|
||||
@@ -610,14 +605,6 @@ class OmniPathNodeMaker : NodeEvaluator() {
|
||||
}
|
||||
}
|
||||
|
||||
fun canWalkOnWater(): Boolean {
|
||||
return if (this.mob is OmniPathingEntity) {
|
||||
(this.mob as OmniPathingEntity).canWalkOnWater()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fun canFly(): Boolean {
|
||||
return if (this.mob is OmniPathingEntity) {
|
||||
(this.mob as OmniPathingEntity).canFly()
|
||||
|
||||
-1
@@ -136,7 +136,6 @@ internal object PropertiesCompletionProvider : DataRegistry {
|
||||
this.inject(setOf("shiny", "s"), setOf("yes", "no"))
|
||||
this.inject(setOf("gender"), Gender.values().map { it.name.lowercase() })
|
||||
this.inject(setOf("friendship"), setOf("0", Cobblemon.config.maxPokemonFriendship.toString()))
|
||||
this.inject(setOf("fullness"), setOf("0", "255"))
|
||||
this.inject(setOf("pokeball"), PokeBalls.all().map { it.name.simplify() })
|
||||
this.inject(setOf("nature"), Natures.all().map { it.name.simplify() })
|
||||
this.inject(setOf("ability"), Abilities.all().map { if (it.name.asIdentifierDefaultingNamespace().namespace == Cobblemon.MODID) it.name.asIdentifierDefaultingNamespace().path else it.name })
|
||||
|
||||
@@ -74,7 +74,7 @@ fun <T> ByteBuf.writeCollection(collection: Collection<T> , writer: (ByteBuf, T)
|
||||
}
|
||||
|
||||
fun <T> ByteBuf.writeNullable(obj: T?, writer: (ByteBuf, T) -> Unit) {
|
||||
this.writeBoolean(obj != null)
|
||||
this.writeBoolean(obj == null)
|
||||
obj?.let {
|
||||
writer(this, it)
|
||||
}
|
||||
@@ -101,11 +101,6 @@ fun ByteBuf.writeExpression(expression: Expression): ByteBuf {
|
||||
return this.writeString(expression.getString())
|
||||
}
|
||||
|
||||
fun ByteBuf.writeNullableExpression(expression: Expression?): ByteBuf {
|
||||
this.writeNullable(expression) { buf, expr -> buf.writeExpression(expr) }
|
||||
return this
|
||||
}
|
||||
|
||||
fun ByteBuf.writeRidingStats(stats: Map<RidingStat, IntRange>) {
|
||||
return this.writeMap(
|
||||
stats,
|
||||
@@ -125,10 +120,6 @@ fun ByteBuf.readExpression(): Expression {
|
||||
return this.readString().asExpression()
|
||||
}
|
||||
|
||||
fun ByteBuf.readNullableExpression(): Expression? {
|
||||
return this.readNullable { buf -> buf.readExpression() }
|
||||
}
|
||||
|
||||
fun <T> ByteBuf.readNullable(reader: (ByteBuf) -> T): T? {
|
||||
val isPresent = this.readBoolean()
|
||||
if (isPresent) {
|
||||
|
||||
@@ -60,7 +60,6 @@ object DataKeys {
|
||||
const val POKEMON_POTENTIAL_MARKS = "Potential Marks"
|
||||
const val POKEMON_MARKINGS = "Markings"
|
||||
const val POKEMON_RIDE_BOOSTS = "RideBoosts"
|
||||
const val POKEMON_RIDE_STAMINA = "RideStamina"
|
||||
|
||||
const val POKEMON_STATE = "State"
|
||||
const val POKEMON_STATE_TYPE = "StateType"
|
||||
|
||||
@@ -27,7 +27,6 @@ import net.minecraft.core.BlockPos
|
||||
import net.minecraft.core.RegistryAccess
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.packs.resources.Resource
|
||||
import net.minecraft.world.InteractionHand
|
||||
import net.minecraft.world.entity.EquipmentSlot
|
||||
import net.minecraft.world.item.ItemStack
|
||||
@@ -36,7 +35,7 @@ import net.minecraft.world.level.pathfinder.Path
|
||||
import net.minecraft.world.phys.shapes.VoxelShape
|
||||
import org.joml.Vector4f
|
||||
|
||||
fun cobblemonResource(path: String): ResourceLocation = ResourceLocation.fromNamespaceAndPath(Cobblemon.MODID, path)
|
||||
fun cobblemonResource(path: String) = ResourceLocation.fromNamespaceAndPath(Cobblemon.MODID, path)
|
||||
fun cobblemonModel(path: String, variant: String) =
|
||||
ModelResourceLocation(cobblemonResource(path), variant)
|
||||
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ import net.minecraft.advancements.critereon.MinMaxBounds
|
||||
import java.lang.reflect.Type
|
||||
|
||||
/**
|
||||
* A type adapter for [MinMaxBounds.Doubles].
|
||||
* A type adapter for [NumberRange.DoubleRange].
|
||||
*
|
||||
* @author Licious
|
||||
* @since November 28th, 2022
|
||||
|
||||
@@ -41,7 +41,6 @@ internal data class PokemonP3(
|
||||
val potentialMarks: Set<ResourceLocation>,
|
||||
val markings: List<Int>,
|
||||
val rideBoosts: Map<String, Float>,
|
||||
val rideStamina: Float,
|
||||
val currentFullness: Int,
|
||||
val interactionCooldowns: Map<ResourceLocation, Int>
|
||||
) : Partial<Pokemon> {
|
||||
@@ -78,7 +77,6 @@ internal data class PokemonP3(
|
||||
other.potentialMarks += this.potentialMarks.map { Marks.getByIdentifier(it) }.filterNotNull().toMutableSet()
|
||||
other.markings = this.markings
|
||||
this.rideBoosts.let { other.setRideBoosts(it.mapKeys { RidingStat.valueOf(it.key) }) }
|
||||
other.rideStamina = this.rideStamina
|
||||
other.currentFullness = this.currentFullness
|
||||
other.interactionCooldowns = this.interactionCooldowns.toMutableMap()
|
||||
return other
|
||||
@@ -99,10 +97,9 @@ internal data class PokemonP3(
|
||||
Codec.list(ResourceLocation.CODEC).optionalFieldOf(DataKeys.POKEMON_POTENTIAL_MARKS, emptyList()).forGetter { it.potentialMarks.toMutableList() },
|
||||
Codec.list(Codec.INT).optionalFieldOf(DataKeys.POKEMON_MARKINGS, listOf(0, 0, 0, 0, 0, 0)).forGetter(PokemonP3::markings),
|
||||
Codec.unboundedMap(Codec.STRING, Codec.FLOAT).optionalFieldOf(DataKeys.POKEMON_RIDE_BOOSTS, emptyMap<String, Float>()).forGetter(PokemonP3::rideBoosts),
|
||||
Codec.FLOAT.optionalFieldOf(DataKeys.POKEMON_RIDE_STAMINA, 1F).forGetter(PokemonP3::rideStamina),
|
||||
Codec.intRange(0, 100).optionalFieldOf(DataKeys.POKEMON_FULLNESS, 0).forGetter(PokemonP3::currentFullness),
|
||||
Codec.unboundedMap(ResourceLocation.CODEC, Codec.INT).optionalFieldOf(DataKeys.POKEMON_INTERACTION_COOLDOWN, emptyMap<ResourceLocation, Int>()).forGetter(PokemonP3::interactionCooldowns)
|
||||
).apply(instance) { originalTrainerType, originalTrainer, forcedAspects, features, heldItemVisible, canDropHeldItem, cosmeticItem, activeMark, marks, potentialMarks, markings, rideBoosts, rideStamina, currentFullness, interactionCooldown -> PokemonP3(originalTrainerType, originalTrainer, forcedAspects.toSet(), features, heldItemVisible, canDropHeldItem, cosmeticItem.orElse(ItemStack.EMPTY), activeMark, marks.toMutableSet(), potentialMarks.toMutableSet(), markings, rideBoosts, rideStamina, currentFullness, interactionCooldown) }
|
||||
).apply(instance) { originalTrainerType, originalTrainer, forcedAspects, features, heldItemVisible, canDropHeldItem, cosmeticItem, activeMark, marks, potentialMarks, markings, rideBoosts, currentFullness, interactionCooldown -> PokemonP3(originalTrainerType, originalTrainer, forcedAspects.toSet(), features, heldItemVisible, canDropHeldItem, cosmeticItem.orElse(ItemStack.EMPTY), activeMark, marks.toMutableSet(), potentialMarks.toMutableSet(), markings, rideBoosts, currentFullness, interactionCooldown) }
|
||||
}
|
||||
|
||||
internal fun from(pokemon: Pokemon): PokemonP3 = PokemonP3(
|
||||
@@ -122,7 +119,6 @@ internal data class PokemonP3(
|
||||
pokemon.potentialMarks.map { it.identifier }.toSet(),
|
||||
pokemon.markings,
|
||||
pokemon.getRideBoosts().mapKeys { it.key.name },
|
||||
pokemon.rideStamina,
|
||||
pokemon.currentFullness,
|
||||
pokemon.interactionCooldowns
|
||||
)
|
||||
|
||||
@@ -6467,9 +6467,9 @@
|
||||
"item.cobblemon.iron.tooltip": "Erhöht die EVs der Vert um 10",
|
||||
"item.cobblemon.protein.tooltip": "Erhöht die EVs des Angriffs um 10",
|
||||
"item.cobblemon.zinc.tooltip": "Erhöht die EVs der Sp. Ver. um 10",
|
||||
"item.cobblemon.potion.tooltip": "Stellt 20 KP eines Pokémon wieder her",
|
||||
"item.cobblemon.super_potion.tooltip": "Stellt 60 KP eines Pokémon wieder her",
|
||||
"item.cobblemon.hyper_potion.tooltip": "Stellt 120 KP eines Pokémon wieder her",
|
||||
"item.cobblemon.potion.tooltip": "Stellt 60 KP eines Pokémon wieder her",
|
||||
"item.cobblemon.super_potion.tooltip": "Stellt 100 KP eines Pokémon wieder her",
|
||||
"item.cobblemon.hyper_potion.tooltip": "Stellt 150 KP eines Pokémon wieder her",
|
||||
"item.cobblemon.max_potion.tooltip": "Stellt sämtliche KP eines Pokémon wieder her",
|
||||
"item.cobblemon.full_restore.tooltip": "Stellt sämtliche KP eines Pokémon wieder her und befreit es von sämtlichen Statusproblemen",
|
||||
"item.cobblemon.health_feather.tooltip": "Erhöht die EVs der KP um 1",
|
||||
@@ -6581,29 +6581,5 @@
|
||||
"item.cobblemon.light_ball.tooltip": "Erhöht Pikachu´s Angriff und Spezial-Angriff",
|
||||
"item.cobblemon.loaded_dice.tooltip": "Serienattacken treffen mindestens viermal",
|
||||
"item.cobblemon.lucky_egg.tooltip": "Erhöht die im Kampf erhaltene EP für den Träger",
|
||||
"item.cobblemon.metronome.tooltip": "Verstärkt eine Attacke, je öfter sie in Folge ausgeführt wird",
|
||||
"item.cobblemon.red_card.tooltip_1": "Pokémon, die dem Träger Schaden zufügen, werden zum Auswechseln gezwungen",
|
||||
"item.cobblemon.scroll_of_darkness": "Unlicht-Schriftrolle",
|
||||
"item.cobblemon.punching_glove.tooltip": "Stärkt die Stärke der Punch-Attacken des Trägers und verhindert, dass diese Kontakt mit dem Ziel herstellen",
|
||||
"item.cobblemon.razor_claw.tooltip_2": "Entwickelt Sniebel zu Snieboss oder Snibunna, wenn es tagsüber bzw. nachts beim Levelaufstieg getragen wird",
|
||||
"item.cobblemon.ring_target.tooltip": "Die Typen-Immunitäten des Trägers werden aufgehoben",
|
||||
"item.cobblemon.safety_goggles.tooltip": "Verleiht dem Träger Immunität gegenüber Puder- und Sporen-Attacken sowie Wetterschaden",
|
||||
"item.cobblemon.hearty_grains": "Munterreis",
|
||||
"item.cobblemon.bugwort": "Schutzblume",
|
||||
"item.cobblemon.metal_alloy": "Legierungsmetall",
|
||||
"item.cobblemon.scroll_of_waters": "Wasser-Schriftrolle",
|
||||
"item.cobblemon.metal_alloy.tooltip": "Entwickelt Duraludon zu Briduradon",
|
||||
"item.cobblemon.scroll_of_darkness.tooltip": "Entwickelt Dakuma zu Wulaosu im Fokussierten Stil",
|
||||
"item.cobblemon.scroll_of_waters.tooltip": "Entwickelt Dakuma zu Wulaosu im Fließenden Stil",
|
||||
"item.cobblemon.potato_mochi": "Kartoffel-Mochi",
|
||||
"item.cobblemon.fried_rice": "Gebratener Reis",
|
||||
"item.cobblemon.candied_apple": "Kandierter Apfel",
|
||||
"item.cobblemon.protective_pads.tooltip": "Schützt den Träger vor Kontakt-Effekten des Ziels",
|
||||
"item.cobblemon.quick_claw.tooltip": "Ermöglicht dem Träger gelegentlich, zuerst anzugreifen",
|
||||
"item.cobblemon.razor_claw.tooltip_1": "Erhöht die Volltrefferquote der Attacken des Trägers",
|
||||
"item.cobblemon.razor_fang.tooltip_1": "Verursacht der Träger Schaden, schreckt das Ziel eventuell zurück",
|
||||
"item.cobblemon.razor_fang.tooltip_2": "Entwickelt Skorgla zu Skorgro, wenn es nachts beim Levelaufstieg getragen wird",
|
||||
"item.cobblemon.rocky_helmet.tooltip": "Fügt einem Pokémon, das direkten Kontakt mit dem Träger herstellt, Schaden zu",
|
||||
"item.cobblemon.room_service.tooltip_1": "Senkt die Initiative des Trägers, wenn Bizarroraum aktiv ist",
|
||||
"item.cobblemon.scope_lens.tooltip": "Erhöht die Volltrefferquote des Trägers"
|
||||
"item.cobblemon.metronome.tooltip": "Verstärkt eine Attacke, je öfter sie in Folge ausgeführt wird"
|
||||
}
|
||||
|
||||
@@ -11,63 +11,5 @@
|
||||
"cobblemon.ui.entity.behaviour_editor": "Behaviours",
|
||||
"cobblemon.ui.entity.behaviour_editor.label": "Behaviours - %1$s",
|
||||
"cobblemon.ui.entity.behaviour_editor.label.active": "Active Behaviours",
|
||||
"cobblemon.ui.entity.behaviour_editor.label.inactive": "Inactive Behaviours",
|
||||
"cobblemon.ui.pokedex.info.form.squawkabilly-color-gray": "Grey",
|
||||
"cobblemon.species.alcremie-rubycream.desc": "The moment it evolved, it took on a sweet and tart flavour. This is because of the way its cells spontaneously shifted during evolution.",
|
||||
"advancements.cobblemon.craft_base_balls.description": "Craft all seven of the basic coloured Poké Balls",
|
||||
"cobblemon.move.aurorabeam.desc": "The target is hit with a rainbow-coloured beam. This may also lower the target's Attack stat.",
|
||||
"cobblemon.species.venusaur.desc": "There is a large flower on Venusaur's back. The flower is said to take on vivid colours if it gets plenty of nutrition and sunlight. The flower's aroma soothes the emotions of people.",
|
||||
"cobblemon.species.charmeleon.desc": "Charmeleon mercilessly destroys its foes using its sharp claws. If it encounters a strong foe, it turns aggressive. In this excited state, the flame at the tip of its tail flares with a bluish white colour.",
|
||||
"cobblemon.species.starmie.desc": "Starmie swims through water by spinning its star-shaped body as if it were a propeller on a ship. The core at the center of this Pokémon's body glows in seven colours.",
|
||||
"cobblemon.species.hooh.desc": "Ho-Oh's feathers glow in seven colours depending on the angle at which they are struck by light. These feathers are said to bring happiness to the bearers. This Pokémon is said to live at the foot of a rainbow.",
|
||||
"cobblemon.species.shellos.desc": "Its shape and colouration vary, depending on its habitat.",
|
||||
"cobblemon.species.vivillon.desc": "The patterns on this Pokémon's wings depend on the climate and topography of its habitat. It scatters colourful scales.",
|
||||
"cobblemon.species.roselia.desc": "On extremely rare occasions, a Roselia is said to appear with its flowers in unusual colours. The thorns on this Pokémon's head contain a vicious poison.",
|
||||
"cobblemon.species.kecleon.desc": "Kecleon alters its body colouration to blend in with its surroundings, allowing it to sneak up on its prey unnoticed. Then it lashes out with its long, stretchy tongue to instantly ensnare the unsuspecting target.",
|
||||
"cobblemon.species.munna.desc": "It eats the dreams of people and Pokémon. When it eats a pleasant dream, it expels pink-coloured mist.",
|
||||
"cobblemon.species.musharna.desc": "The dream mist coming from its forehead changes into many different colours depending on the dream that was eaten.",
|
||||
"cobblemon.species.basculin-bluestriped.desc": "These Pokémon form schools with others of the same colour. The greatest foe of a school of blue Basculin is a school of red Basculin.",
|
||||
"cobblemon.species.xerneas.desc": "When the horns on its head shine in seven colours, it is said to be sharing everlasting life.",
|
||||
"cobblemon.species.minior.desc": "This is its form when its shell has fallen off. The colour of its core depends on the materials that made up the food it ate.",
|
||||
"cobblemon.species.minior-indigo.desc": "This is its form when its shell has fallen off. The colour of its core depends on the materials that made up the food it ate.",
|
||||
"cobblemon.species.minior-violet.desc": "This is its form when its shell has fallen off. The colour of its core depends on the materials that made up the food it ate.",
|
||||
"cobblemon.species.swinub.desc": "Swinub roots for food by rubbing its snout against the ground. Its favourite food is a mushroom that grows under the cover of dead grass. This Pokémon occasionally roots out hot springs.",
|
||||
"cobblemon.species.fomantis.desc": "It loves the sunshine. When it basks in the sunlight regularly, it grows up with vivid colouration.",
|
||||
"cobblemon.species.minior-green.desc": "This is its form when its shell has fallen off. The colour of its core depends on the materials that made up the food it ate.",
|
||||
"cobblemon.species.graveler.desc": "Rocks are Graveler's favourite food. This Pokémon will climb a mountain from the base to the summit, crunchingly feasting on rocks all the while. Upon reaching the peak, it rolls back down to the bottom.",
|
||||
"cobblemon.species.minior-blue.desc": "This is its form when its shell has fallen off. The colour of its core depends on the materials that made up the food it ate.",
|
||||
"cobblemon.species.ducklett.desc": "They are better at swimming than flying, and they happily eat their favourite food, peat moss, as they dive underwater.",
|
||||
"cobblemon.item_class.flavor_seasoning": "Flavour Seasoning",
|
||||
"cobblemon.seasoning_flavor_header": "Flavour",
|
||||
"cobblemon.seasoning_flavor_info_header": "Flavour Info:",
|
||||
"cobblemon.ui.pokedex.info.form.color-light_gray": "Light Grey",
|
||||
"cobblemon.ui.pokedex.info.form.color-gray": "Grey",
|
||||
"advancements.cobblemon.first_shiny_catch": "Lucky Colour",
|
||||
"advancements.cobblemon.obtain_all_mints.description": "Obtain all 6 colours of Nature Mint and gain access to a full array of natures",
|
||||
"cobblemon.species.wartortle.desc": "Its tail is large and covered with a rich, thick fur. The tail becomes increasingly deeper in colour as Wartortle ages. The scratches on its shell are evidence of this Pokémon's toughness as a battler.",
|
||||
"cobblemon.species.weedle.desc": "Weedle has an extremely acute sense of smell. It is capable of distinguishing its favourite kinds of leaves from those it dislikes just by sniffing with its big red proboscis (nose).",
|
||||
"cobblemon.species.venomoth.desc": "Venomoth is nocturnal—it is a Pokémon that only becomes active at night. Its favourite prey are small insects that gather around streetlights, attracted by the light in the darkness.",
|
||||
"cobblemon.species.muk.desc": "This Pokémon's favourite food is anything that is repugnantly filthy. In dirty towns where people think nothing of throwing away litter on the streets, Muk are certain to gather.",
|
||||
"cobblemon.species.florges-white.desc": "A flower garden made by a white-flowered Florges will be beautifully decorated with flowering plants of many different colours.",
|
||||
"cobblemon.species.deerling.desc": "The turning of the seasons changes the colour and scent of this Pokémon's fur. People use it to mark the seasons.",
|
||||
"cobblemon.species.floette-orange.desc": "This Pokémon can draw forth the most power when in sync with orange flowers, compared to flowers of other colours.",
|
||||
"cobblemon.species.floette-white.desc": "Floette that are fond of white flowers can also easily sync with flowers of other colours.",
|
||||
"cobblemon.species.xerneas-active.desc": "When the horns on its head shine in seven colours, it is said to be sharing everlasting life.",
|
||||
"cobblemon.species.gumshoos.desc": "Patient by nature, this Pokémon loses control of itself and pounces when it spots its favourite meal—Rattata!",
|
||||
"cobblemon.species.minior-orange.desc": "This is its form when its shell has fallen off. The colour of its core depends on the materials that made up the food it ate.",
|
||||
"cobblemon.species.minior-yellow.desc": "This is its form when its shell has fallen off. The colour of its core depends on the materials that made up the food it ate.",
|
||||
"cobblemon.ui.pokedex.info.form.magearna-original": "Original Colour",
|
||||
"cobblemon.species.polteageist-antique.desc": "Trainers Polteageist trusts will be allowed to experience its distinctive flavour and aroma firsthand by sampling just a tiny bit of its tea.",
|
||||
"cobblemon.species.alcremie-matchacream.desc": "The moment it evolved, it took on an aromatic flavour. This is because of the way its cells spontaneously shifted during evolution.",
|
||||
"cobblemon.species.alcremie-mintcream.desc": "The moment it evolved, it took on a refreshing flavour. This is because of the way its cells spontaneously shifted during evolution.",
|
||||
"cobblemon.species.alcremie-lemoncream.desc": "The moment it evolved, it took on a sour flavour. This is because of the way its cells spontaneously shifted during evolution.",
|
||||
"cobblemon.species.alcremie-saltedcream.desc": "The moment it evolved, it took on a salty flavour. This is because of the way its cells spontaneously shifted during evolution.",
|
||||
"cobblemon.species.alcremie-rubyswirl.desc": "The moment it evolved, it took on a mixed flavour. This is because of the way its cells spontaneously shifted during evolution.",
|
||||
"cobblemon.species.alcremie-caramelswirl.desc": "The moment it evolved, it took on a bitter flavour. This is because of the way its cells spontaneously shifted during evolution.",
|
||||
"cobblemon.species.alcremie-rainbowswirl.desc": "The moment it evolved, it took on a complex flavour. This is because of the way its cells spontaneously shifted during evolution.",
|
||||
"cobblemon.species.squawkabilly.desc": "These Pokémon prefer to live in cities. They form flocks based on the colour of their feathers, and they fight over territory.",
|
||||
"cobblemon.species.tatsugiri-droopy.desc": "This species' differing colours and patterns are apparently the result of Tatsugiri changing itself to suit the preferences of the prey it lures in.",
|
||||
"cobblemon.species.grafaiai.desc": "The colour of the poisonous saliva depends on what the Pokémon eats. Grafaiai covers its fingers in its saliva and draws patterns on trees in forests.",
|
||||
"cobblemon.species.veluza.desc": "When Veluza discards unnecessary flesh, its mind becomes honed and its psychic power increases. The spare flesh has a mild but delicious flavour.",
|
||||
"cobblemon.ability.colorchange": "Colour Change"
|
||||
"cobblemon.ui.entity.behaviour_editor.label.inactive": "Inactive Behaviours"
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -739,17 +739,17 @@
|
||||
"item.cobblemon.sky_tumblestone": "Sky Tumblestone",
|
||||
|
||||
"item.cobblemon.health_mochi": "Health Mochi",
|
||||
"item.cobblemon.health_mochi.tooltip": "Raises the Pokémon's HP EVs by 4",
|
||||
"item.cobblemon.health_mochi.tooltip": "Raises the Pokémon's HP EVs by 10",
|
||||
"item.cobblemon.muscle_mochi": "Muscle Mochi",
|
||||
"item.cobblemon.muscle_mochi.tooltip": "Raises the Pokémon's Attack EVs by 4",
|
||||
"item.cobblemon.muscle_mochi.tooltip": "Raises the Pokémon's Attack EVs by 10",
|
||||
"item.cobblemon.resist_mochi": "Resist Mochi",
|
||||
"item.cobblemon.resist_mochi.tooltip": "Raises the Pokémon's Defense EVs by 4",
|
||||
"item.cobblemon.resist_mochi.tooltip": "Raises the Pokémon's Defense EVs by 10",
|
||||
"item.cobblemon.genius_mochi": "Genius Mochi",
|
||||
"item.cobblemon.genius_mochi.tooltip": "Raises the Pokémon's Sp. Atk EVs by 4",
|
||||
"item.cobblemon.genius_mochi.tooltip": "Raises the Pokémon's Sp. Atk EVs by 10",
|
||||
"item.cobblemon.clever_mochi": "Clever Mochi",
|
||||
"item.cobblemon.clever_mochi.tooltip": "Raises the Pokémon's Sp. Def EVs by 4",
|
||||
"item.cobblemon.clever_mochi.tooltip": "Raises the Pokémon's Sp. Def EVs by 10",
|
||||
"item.cobblemon.swift_mochi": "Swift Mochi",
|
||||
"item.cobblemon.swift_mochi.tooltip": "Raises the Pokémon's Speed EVs by 4",
|
||||
"item.cobblemon.swift_mochi.tooltip": "Raises the Pokémon's Speed EVs by 10",
|
||||
"item.cobblemon.fresh_start_mochi": "Fresh-Start Mochi",
|
||||
"item.cobblemon.fresh_start_mochi.tooltip": "Resets all of the Pokémon's EVs to 0",
|
||||
|
||||
@@ -1117,10 +1117,6 @@
|
||||
"cobblemon.ui.generic.no": "No",
|
||||
"cobblemon.ui.generic.save": "Save",
|
||||
|
||||
"cobblemon.ui.ride_style.air": "Air",
|
||||
"cobblemon.ui.ride_style.land": "Land",
|
||||
"cobblemon.ui.ride_style.liquid": "Liquid",
|
||||
|
||||
"cobblemon.container.campfire_pot": "Campfire Pot",
|
||||
"cobblemon.container.campfire_pot.recipe_book.toggle_recipes": "Showing Cookable",
|
||||
|
||||
@@ -1147,22 +1143,14 @@
|
||||
"cobblemon.ui.stats.stat": "Stat",
|
||||
"cobblemon.ui.stats.ivs": "IVs",
|
||||
"cobblemon.ui.stats.evs": "EVs",
|
||||
"cobblemon.ui.stats.ride": "Ride",
|
||||
"cobblemon.ui.stats.other": "Other",
|
||||
"cobblemon.ui.stats.friendship": "Friendship",
|
||||
"cobblemon.ui.stats.fullness": "Fullness",
|
||||
"cobblemon.ui.stats.hp": "HP",
|
||||
"cobblemon.ui.stats.atk": "Atk",
|
||||
"cobblemon.ui.stats.def": "Def",
|
||||
"cobblemon.ui.stats.sp_atk": "Sp.Atk",
|
||||
"cobblemon.ui.stats.sp_def": "Sp.Def",
|
||||
"cobblemon.ui.stats.speed": "Speed",
|
||||
"cobblemon.ui.stats.ride.acceleration": "Accel.",
|
||||
"cobblemon.ui.stats.ride.jump": "Jump",
|
||||
"cobblemon.ui.stats.ride.skill": "Skill",
|
||||
"cobblemon.ui.stats.ride.speed": "Speed",
|
||||
"cobblemon.ui.stats.ride.stamina": "Stamina",
|
||||
"cobblemon.ui.stats.ride.boost_maximum": "Boosted Maximum",
|
||||
|
||||
"cobblemon.ui.stash.gold": "Coin Stash",
|
||||
"cobblemon.ui.stash.netherite": "Scrap Stash",
|
||||
@@ -1258,8 +1246,6 @@
|
||||
"cobblemon.ui.pokedex.info.ability": "Ability: %1$s",
|
||||
"cobblemon.ui.pokedex.info.entry": "Entry",
|
||||
"cobblemon.ui.pokedex.info.stats": "Base Stats",
|
||||
"cobblemon.ui.pokedex.info.stats_ride": "Ride Stats",
|
||||
"cobblemon.ui.pokedex.info.stats_ride.seats": "Seats: %1$s",
|
||||
"cobblemon.ui.pokedex.info.drops": "Drops",
|
||||
"cobblemon.ui.pokedex.info.drops_display": "%1$s %2$s",
|
||||
"cobblemon.ui.pokedex.info.drops_amount": "%1$s×",
|
||||
@@ -2365,9 +2351,6 @@
|
||||
"cobblemon.command.pokemonrestart": "Cleared %1$s's party and PC.",
|
||||
"cobblemon.command.freezepokemon.non_pokemon": "You are not looking at a Pokémon.",
|
||||
"cobblemon.command.npcedit.non_npc": "You are not looking at a NPC.",
|
||||
"cobblemon.command.npcdelete.not_player": "Only players may run this command.",
|
||||
"cobblemon.command.npcdelete.deleted": "%1$s has been deleted.",
|
||||
|
||||
"cobblemon.command.cobblemon_config.reload": "Reloading Cobblemon settings.",
|
||||
"cobblemon.command.unlockboxwallpaper.success": "%1$s can now use the %2$s wallpaper.",
|
||||
"cobblemon.command.unlockboxwallpaper.already": "%1$s already has the %2$s wallpaper.",
|
||||
@@ -2588,10 +2571,6 @@
|
||||
"cobblemon.config.ui.despawner_max_age_ticks.tooltip": "The age (in game ticks) a Pokémon must reach before it can be despawned at the near distance boundary.",
|
||||
"cobblemon.config.ui.enable_debug_keys": "Enable Debug Keys",
|
||||
"cobblemon.config.ui.enable_debug_keys.tooltip": "Enables additional commands and chat logging to assist with implementing Pokémon (see the wiki for a list of commands).",
|
||||
"cobblemon.config.ui.infinite_ride_stamina": "Infinite Ride Stamina",
|
||||
"cobblemon.config.ui.infinite_ride_stamina.tooltip": "Whether rideable Pokémon have infinite stamina.",
|
||||
"cobblemon.config.ui.remember_riding_camera": "Remember Riding Camera",
|
||||
"cobblemon.config.ui.remember_riding_camera.tooltip": "Whether the camera mode will automatically switch to the last used camera mode when mounting a rideable Pokémon.",
|
||||
|
||||
"cobblemon.config.ui.allow_starter_on_join": "Allow Starter on Join",
|
||||
"cobblemon.config.ui.prompt_starter_once_only": "Prompt Starter Once Only",
|
||||
@@ -2721,6 +2700,7 @@
|
||||
"cobblemon.battle.lose": "%1$s is out of usable Pokémon!",
|
||||
"cobblemon.battle.forfeit": "%1$s forfeited the battle!",
|
||||
"cobblemon.battle.flee": "The battle was fled.",
|
||||
"cobblemon.battle.wild_flee": "The wild %1$s fled.",
|
||||
"cobblemon.battle.switch_option": "Switch Pokémon: ",
|
||||
"cobblemon.battle.your_team": "Your Team:",
|
||||
"cobblemon.battle.must_switch": "Choose a Pokémon to switch in",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2359,184 +2359,5 @@
|
||||
"cobblemon.mark.ribbon_ability_great.desc": "Una cinta obtenida por derrotar al Amo de la Torre en la Torre Batalla.",
|
||||
"cobblemon.mark.ribbon_ability_world.desc": "Una cinta obtenida por completar el Desafío Wi-Fi de la Torre Batalla.",
|
||||
"cobblemon.mark.ribbon_battler_expert.desc": "Una cinta que se le otorga a valientes Pokémon que ha dominado con maestría el arte de combatir.",
|
||||
"cobblemon.fishing.no_bite": "Nada. Ni un mordisco.",
|
||||
"item.cobblemon.genius_mochi.tooltip": "Aumenta los EVs de Ataque Especial del Pokémon en 10",
|
||||
"item.cobblemon.health_mochi.tooltip": "Aumenta los EVs de PS del Pokémon en 10",
|
||||
"item.cobblemon.health_mochi": "Mochi Salud",
|
||||
"item.cobblemon.clever_mochi": "Mochi Mente",
|
||||
"item.cobblemon.muscle_mochi": "Mochi Fuerza",
|
||||
"item.cobblemon.muscle_mochi.tooltip": "Aumenta los EVs de Ataque del Pokémon en 10",
|
||||
"item.cobblemon.resist_mochi": "Mochi Resistencia",
|
||||
"item.cobblemon.resist_mochi.tooltip": "Aumenta los EVs de Defensa del Pokémon en 10",
|
||||
"item.cobblemon.genius_mochi": "Mochi Inteligencia",
|
||||
"item.cobblemon.clever_mochi.tooltip": "Aumenta los EVs de Defensa Especial del Pokémon en 10",
|
||||
"item.cobblemon.swift_mochi": "Mochi Instantáneo",
|
||||
"item.cobblemon.swift_mochi.tooltip": "Aumenta los EVs de Velocidad del Pokémon en 10",
|
||||
"item.cobblemon.fresh_start_mochi": "Mochi Reinicio",
|
||||
"item.cobblemon.fresh_start_mochi.tooltip": "Reinicia todos los EVs del Pokémon, dejándolos en 0",
|
||||
"item.cobblemon.aprijuice.prefix.delicious": "Delicioso",
|
||||
"item.cobblemon.aprijuice.quality_format": "%2$s %1$s",
|
||||
"item.cobblemon.aprijuice.prefix.tasty": "Sabroso",
|
||||
"item.cobblemon.aprijuice_black": "Bongurijugo Negro",
|
||||
"item.cobblemon.aprijuice_blue": "Bongurijugo Azul",
|
||||
"item.cobblemon.aprijuice_green": "Bongurijugo Verde",
|
||||
"item.cobblemon.aprijuice_pink": "Bongurijugo Rosa",
|
||||
"item.cobblemon.aprijuice_red": "Bongurijugo Rojo",
|
||||
"item.cobblemon.aprijuice_white": "Bongurijugo Blanco",
|
||||
"item.cobblemon.aprijuice_yellow": "Bongurijugo Amarillo",
|
||||
"item.cobblemon.tasty_tail": "Cola Deliciosa",
|
||||
"item.cobblemon.candied_berry": "Bayas Confitadas",
|
||||
"item.cobblemon.pewter_crunchies": "Rokikos",
|
||||
"item.cobblemon.rage_candy_bar": "Caramelo Furia",
|
||||
"item.cobblemon.lava_cookie": "Galleta Lava",
|
||||
"item.cobblemon.jubilife_muffin": "Bizcocho Jubileo",
|
||||
"item.cobblemon.aprijuice.prefix.plain": "Natural",
|
||||
"item.cobblemon.old_gateau": "Viejo Pastél",
|
||||
"item.cobblemon.shalour_sable": "Galleta Yantra",
|
||||
"item.cobblemon.casteliacone": "Castehelado",
|
||||
"item.cobblemon.lumiose_galette": "Crepa Lumiose",
|
||||
"item.cobblemon.big_malasada": "Malasada Maxi",
|
||||
"cobblemon.tooltip.mob_effect_entry": "%1$s %2$s (%3$s)",
|
||||
"item.cobblemon.hearty_grains": "Espiga Vivaz",
|
||||
"item.cobblemon.saccharine_sapling": "Brote de Sacarina",
|
||||
"item.cobblemon.saccharine_boat": "Bote de Sacarina",
|
||||
"item.cobblemon.scroll_of_darkness.tooltip": "Hace evolucionar a Kubfu en Urshifu estilo Brusco",
|
||||
"entity.cobblemon.npc": "PNJ",
|
||||
"block.cobblemon.potted_yellow_apricorn_sapling": "Brote de Bonguri Amarillo en Maceta",
|
||||
"block.cobblemon.potted_black_apricorn_sapling": "Brote de Bonguri Negro en Maceta",
|
||||
"block.cobblemon.saccharine_slab": "Losa de Sacarina",
|
||||
"block.cobblemon.saccharine_hanging_sign": "Cartel colgante de Sacarina",
|
||||
"block.cobblemon.potted_saccharine_sapling": "Brote de Sacarina en Maceta",
|
||||
"item.cobblemon.bugwort": "Hierba Repelente",
|
||||
"item.cobblemon.saccharine_chest_boat": "Bote de Sacarina con Cofre",
|
||||
"item.cobblemon.metal_alloy": "Metal Compuesto",
|
||||
"item.cobblemon.metal_alloy.tooltip": "Hace evolucionar a Duraludon en Archaludon",
|
||||
"item.cobblemon.scroll_of_darkness": "Manuscrito Sombras",
|
||||
"item.cobblemon.scroll_of_waters": "Manuscrito Aguas",
|
||||
"item.cobblemon.scroll_of_waters.tooltip": "Hace evolucionar a Kubfu en Urshifu estilo Fluido",
|
||||
"item.cobblemon.potato_mochi": "Mochi de Papa",
|
||||
"item.cobblemon.fried_rice": "Arroz Frito",
|
||||
"item.cobblemon.candied_apple": "Manzana Confitada",
|
||||
"item.cobblemon.moomoo_milk": "Leche Moomoo",
|
||||
"item.cobblemon.poke_bait": "Poké Cebo",
|
||||
"item.cobblemon.smoked_tail_curry": "Curry de Cola Ahumada",
|
||||
"item.cobblemon.open_faced_sandwich": "Sandwich Abierto",
|
||||
"cobblemon.item_class.seasonings": "Condimentos",
|
||||
"cobblemon.item_class.flavor_seasoning": "Condimentos de Sabor",
|
||||
"cobblemon.item_class.bait_effect_seasoning": "Condimentos de Cebo",
|
||||
"cobblemon.item_class.mob_effect_seasoning": "Condimento de Efecto",
|
||||
"cobblemon.item_class.food_seasoning": "Condimento de Comida",
|
||||
"cobblemon.seasoning_bait_effect_header": "Cebo",
|
||||
"cobblemon.seasoning_mob_effect_header": "Efecto",
|
||||
"cobblemon.seasoning_food_header": "Comida",
|
||||
"cobblemon.seasoning_flavor_header": "Sabor",
|
||||
"cobblemon.seasoning_bait_effect_info_header": "Información de Cebo:",
|
||||
"cobblemon.item_class.cooking_pot_recipe_absorbs": "Absorbe",
|
||||
"cobblemon.seasoning_mob_effect_info_header": "Información de Efecto:",
|
||||
"cobblemon.seasoning_food_info_header": "Información de Comida:",
|
||||
"cobblemon.seasoning_flavor_info_header": "Información de Sabor:",
|
||||
"cobblemon.seasoning_flavor.spicy": "Picante",
|
||||
"cobblemon.seasoning_flavor.dry": "Seca",
|
||||
"cobblemon.seasoning_flavor.sweet": "Dulce",
|
||||
"cobblemon.seasoning_flavor.bitter": "Amarga",
|
||||
"cobblemon.seasoning_flavor.sour": "Agria",
|
||||
"cobblemon.cooking.cooking_quality": "Calidad: %1$s",
|
||||
"cobblemon.cooking.cooking_quality.low": "Baja",
|
||||
"cobblemon.cooking.cooking_quality.medium": "Media",
|
||||
"cobblemon.cooking.cooking_quality.high": "Alta",
|
||||
"cobblemon.tooltip.food.hunger": "Hambre: %s",
|
||||
"cobblemon.tooltip.food.saturation": "Saturación: %s",
|
||||
"block.cobblemon.potted_blue_apricorn_sapling": "Brote de Bonguri Azul en Maceta",
|
||||
"block.cobblemon.potted_green_apricorn_sapling": "Brote de Bonguri Verde en Maceta",
|
||||
"block.cobblemon.potted_pink_apricorn_sapling": "Brote de Bonguri Rosa en Maceta",
|
||||
"block.cobblemon.potted_red_apricorn_sapling": "Brote de Bonguri Rojo en Maceta",
|
||||
"block.cobblemon.potted_white_apricorn_sapling": "Brote de Bonguri Blanco en Maceta",
|
||||
"block.cobblemon.saccharine_log": "Tronco de Sacarina",
|
||||
"block.cobblemon.stripped_saccharine_log": "Tronco de Sacarina sin corteza",
|
||||
"block.cobblemon.saccharine_wood": "Leño de Sacarina",
|
||||
"block.cobblemon.stripped_saccharine_wood": "Leño de Sacarina sin corteza",
|
||||
"block.cobblemon.saccharine_honey_log": "Tronco de Sacarina cubierto de Miel",
|
||||
"block.cobblemon.saccharine_planks": "Madera de Sacarina",
|
||||
"block.cobblemon.saccharine_leaves": "Hojas de Sacarina",
|
||||
"block.cobblemon.saccharine_stairs": "Escaleras de Sacarina",
|
||||
"block.cobblemon.saccharine_fence": "Valla de Sacarina",
|
||||
"block.cobblemon.saccharine_fence_gate": "Puerta de valla de Sacarina",
|
||||
"block.cobblemon.saccharine_sign": "Cartel de Sacarina",
|
||||
"block.cobblemon.saccharine_pressure_plate": "Placa de presión de Sacarina",
|
||||
"block.cobblemon.saccharine_button": "Botón de Sacarina",
|
||||
"block.cobblemon.saccharine_door": "Puerta de Sacarina",
|
||||
"block.cobblemon.saccharine_trapdoor": "Trampilla de Sacarina",
|
||||
"block.cobblemon.saccharine_sapling": "Brote de Sacarina",
|
||||
"block.cobblemon.galarica_nut_bush": "Arbusto de Frutos Galanuez",
|
||||
"block.cobblemon.campfire": "Fogata",
|
||||
"block.cobblemon.campfire_pot_black": "Olla Negra para Fogata",
|
||||
"block.cobblemon.campfire_pot_blue": "Olla Azul para Fogata",
|
||||
"block.cobblemon.campfire_pot_green": "Olla Verde para Fogata",
|
||||
"block.cobblemon.campfire_pot_pink": "Olla Rosa para Fogata",
|
||||
"block.cobblemon.campfire_pot_red": "Olla Roja para Fogata",
|
||||
"block.cobblemon.campfire_pot_white": "Olla Blanca para Fogata",
|
||||
"block.cobblemon.campfire_pot_yellow": "Olla Amarilla para Fogata",
|
||||
"block.cobblemon.hearty_grain_bale": "Paca de Espiga Vivaz",
|
||||
"block.cobblemon.tatami_block": "Tatami",
|
||||
"block.cobblemon.tatami_mat": "Alfombra de Tatami",
|
||||
"cobblemon.mark.ribbon_champion_kalos.desc": "Cinta obtenida por ganarle al Campeón de Kalos.",
|
||||
"cobblemon.mark.ribbon_battler_skillful.title": "%1$s el Figura",
|
||||
"cobblemon.mark.ribbon_battler_skillful.desc": "Cinta que se concede a un Pokémon que haya obtenido la victoria en combates complicados.",
|
||||
"cobblemon.mark.ribbon_champion_alola.title": "%1$s el Campeón de Alola",
|
||||
"cobblemon.mark.ribbon_champion_kalos.title": "%1$s el Campeón de Kalos",
|
||||
"cobblemon.mark.ribbon_champion_sinnoh.desc": "Cinta obtenida por ganarle al Campeón de Sinnoh.",
|
||||
"cobblemon.mark.ribbon_contest_hoenn_cool_1": "Cinta Carisma",
|
||||
"cobblemon.mark.ribbon_contest_hoenn_cool_4.desc": "¡Ganador del nivel experto del concurso de carisma!",
|
||||
"cobblemon.mark.ribbon_contest_hoenn_beauty_4.desc": "¡Ganador del nivel experto del concurso de belleza!",
|
||||
"cobblemon.mark.ribbon_contest_hoenn_cool_1.desc": "¡Ganador del nivel normal del concurso de carisma!",
|
||||
"cobblemon.mark.ribbon_contest_hoenn_smart_2.desc": "¡Ganador del nivel alto del concurso de ingenio!",
|
||||
"cobblemon.mark.ribbon_contest_hoenn_cute_4": "Cinta Dulzura Experto",
|
||||
"cobblemon.mark.ribbon_battler_skillful": "Cinta Figura del Combate",
|
||||
"cobblemon.mark.ribbon_best_friends": "Cinta Afecto",
|
||||
"cobblemon.mark.ribbon_best_friends.title": "%1$s, tu mejor amigo",
|
||||
"cobblemon.mark.ribbon_best_friends.desc": "Cinta que se concede a un Pokémon con el que compartes un profundo lazo de amistad.",
|
||||
"cobblemon.mark.ribbon_champion": "Cinta Campeón",
|
||||
"cobblemon.mark.ribbon_champion.title": "%1$s el Campeón",
|
||||
"cobblemon.mark.ribbon_champion.desc": "Cinta obtenida por ganar la Liga Pokémon.",
|
||||
"cobblemon.mark.ribbon_champion_alola": "Cinta Campeón de Alola",
|
||||
"cobblemon.mark.ribbon_champion_alola.desc": "Cinta obtenida por volverte el Campeón de Alola.",
|
||||
"cobblemon.mark.ribbon_champion_galar": "Cinta Campeón de Galar",
|
||||
"cobblemon.mark.ribbon_champion_galar.title": "%1$s el Campeón de Galar",
|
||||
"cobblemon.mark.ribbon_champion_galar.desc": "Cinta que se recibe al volverte el campeón de Galar.",
|
||||
"cobblemon.mark.ribbon_champion_hoenn": "Cinta Campeón de Hoenn",
|
||||
"cobblemon.mark.ribbon_champion_hoenn.title": "%1$s el Campeón de Hoenn",
|
||||
"cobblemon.mark.ribbon_champion_hoenn.desc": "Cinta obtenida por ganarle al Campeón de Hoenn.",
|
||||
"cobblemon.mark.ribbon_champion_kalos": "Cinta Campeón de Kalos",
|
||||
"cobblemon.mark.ribbon_champion_paldea": "Cinta Campeón de Paldea",
|
||||
"cobblemon.mark.ribbon_champion_paldea.title": "%1$s el Campeón de Paldea",
|
||||
"cobblemon.mark.ribbon_champion_paldea.desc": "Cinta que se recibe al volverte el campeón de Paldea.",
|
||||
"cobblemon.mark.ribbon_champion_sinnoh": "Cinta Campeón de Sinnoh",
|
||||
"cobblemon.mark.ribbon_champion_sinnoh.title": "%1$s el Campeón de Sinnoh",
|
||||
"cobblemon.mark.ribbon_contest_hoenn_beauty_1": "Cinta Belleza",
|
||||
"cobblemon.mark.ribbon_contest_hoenn_beauty_1.desc": "¡Ganador del nivel normal del concurso de belleza!",
|
||||
"cobblemon.mark.ribbon_contest_hoenn_beauty_2": "Cinta Belleza Alto",
|
||||
"cobblemon.mark.ribbon_contest_hoenn_beauty_2.desc": "¡Ganador del nivel alto del concurso de belleza!",
|
||||
"cobblemon.mark.ribbon_contest_hoenn_beauty_3": "Cinta Belleza Avanzado",
|
||||
"cobblemon.mark.ribbon_contest_hoenn_beauty_3.desc": "¡Ganador del nivel avanzado del concurso de belleza!",
|
||||
"cobblemon.mark.ribbon_contest_hoenn_beauty_4": "Cinta Belleza Experto",
|
||||
"cobblemon.mark.ribbon_contest_hoenn_cool_2": "Cinta Carisma Alto",
|
||||
"cobblemon.mark.ribbon_contest_hoenn_cool_2.desc": "¡Ganador del nivel alto del concurso de carisma!",
|
||||
"cobblemon.mark.ribbon_contest_hoenn_cool_3": "Cinta Carisma Avanzado",
|
||||
"cobblemon.mark.ribbon_contest_hoenn_cool_3.desc": "¡Ganador del nivel avanzado del concurso de carisma!",
|
||||
"cobblemon.mark.ribbon_contest_hoenn_cool_4": "Cinta Carisma Experto",
|
||||
"cobblemon.mark.ribbon_contest_hoenn_cute_1": "Cinta Dulzura",
|
||||
"cobblemon.mark.ribbon_contest_hoenn_cute_1.desc": "¡Ganador del nivel normal del concurso de dulzura!",
|
||||
"cobblemon.mark.ribbon_contest_hoenn_cute_2": "Cinta Dulzura Alto",
|
||||
"cobblemon.mark.ribbon_contest_hoenn_cute_2.desc": "¡Ganador del nivel alto del concurso de dulzura!",
|
||||
"cobblemon.mark.ribbon_contest_hoenn_cute_3": "Cinta Dulzura Avanzado",
|
||||
"cobblemon.mark.ribbon_contest_hoenn_cute_3.desc": "¡Ganador del nivel avanzado del concurso de dulzura!",
|
||||
"cobblemon.mark.ribbon_contest_hoenn_cute_4.desc": "¡Ganador del nivel experto del concurso de dulzura!",
|
||||
"cobblemon.mark.ribbon_contest_hoenn_smart_1": "Cinta Ingenio",
|
||||
"cobblemon.mark.ribbon_contest_hoenn_smart_1.desc": "¡Ganador del nivel normal del concurso de ingenio!",
|
||||
"cobblemon.mark.ribbon_contest_hoenn_smart_2": "Cinta Ingenio Alto",
|
||||
"cobblemon.mark.ribbon_contest_hoenn_smart_3": "Cinta Ingenio Avanzado",
|
||||
"cobblemon.mark.ribbon_contest_hoenn_smart_3.desc": "¡Ganador del nivel avanzado del concurso de ingenio!",
|
||||
"cobblemon.mark.ribbon_contest_hoenn_smart_4": "Cinta Ingenio Experto",
|
||||
"cobblemon.mark.ribbon_contest_hoenn_smart_4.desc": "¡Ganador del nivel experto del concurso de ingenio!",
|
||||
"cobblemon.mark.ribbon_contest_hoenn_tough_1": "Cinta Dureza"
|
||||
"cobblemon.fishing.no_bite": "Nada. Ni un mordisco."
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user