forked from mirrors/cobblemon
Compare commits
65
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1986cb480b | ||
|
|
c8b0f36049 | ||
|
|
be2a0be806 | ||
|
|
ba4d42ccf6 | ||
|
|
5545d3498f | ||
|
|
641bd7ebaa | ||
|
|
234c4fa0d4 | ||
|
|
3dfda71ed5 | ||
|
|
65ee6de93f | ||
|
|
be88b727bc | ||
|
|
a69fc462ee | ||
|
|
7d5c30d27c | ||
|
|
f7c9c9d4f4 | ||
|
|
41bc14168a | ||
|
|
9540c38a72 | ||
|
|
7a96ed7cd1 | ||
|
|
677adc8d2f | ||
|
|
a99b1dfc6c | ||
|
|
4a718ad0f6 | ||
|
|
ddd417d458 | ||
|
|
10a12a897e | ||
|
|
9fce99ed73 | ||
|
|
c35f60dd5d | ||
|
|
54e5a5e819 | ||
|
|
79ae35ea9e | ||
|
|
58f85e6d0d | ||
|
|
71bfdf41f4 | ||
|
|
9976965673 | ||
|
|
098df1a5a6 | ||
|
|
f49f34efa3 | ||
|
|
eac19929c4 | ||
|
|
59cced5b2c | ||
|
|
f07707221f | ||
|
|
89b89592ab | ||
|
|
cdeb977769 | ||
|
|
a3987b433c | ||
|
|
99de91bd7e | ||
|
|
4b292b1241 | ||
|
|
1e6e4d8c5f | ||
|
|
9a61c3471b | ||
|
|
77f7439853 | ||
|
|
e9718b7e8b | ||
|
|
4cadd4e20f | ||
|
|
17a3d86324 | ||
|
|
48653073f5 | ||
|
|
82c7c03e28 | ||
|
|
2d7f3257d1 | ||
|
|
bc7b4f94c2 | ||
|
|
7a9e9d7ced | ||
|
|
0f85ece16f | ||
|
|
c4656e1a4e | ||
|
|
0c48a318c5 | ||
|
|
dab89a9f8c | ||
|
|
53fd2dba2d | ||
|
|
a5b15c6127 | ||
|
|
174fb59bbb | ||
|
|
2f8bd44938 | ||
|
|
9d58c7126e | ||
|
|
2afd722125 | ||
|
|
c9cfe489d6 | ||
|
|
4ee029fa54 | ||
|
|
d1a8171079 | ||
|
|
d4b673ea38 | ||
|
|
de21b7c402 | ||
|
|
10fe3c4362 |
@@ -397,6 +397,9 @@
|
||||
- Fixed Alolan Exeggutor's tail not showing in the party UI. It will now also stand in front of all Pokémon in the party menu :)
|
||||
- Fixed Timburr duplicating its log while fainting.
|
||||
- Fixed hitbox sizes for Grotle and Torterra being set to default values.
|
||||
- Fixed Hisuian Sneasel using Johtonian Sneasel's cry
|
||||
- Fixed Trevenant t-posing after 8 seconds of sleep.
|
||||
- Fixed Bewear t-posing for a bit if a wild one fainted.
|
||||
- Fixed reviving items throwing an exception when used in battle.
|
||||
- Fixed messages for Focus Sash, Confusion, Mummy, Ice Face, Own Tempo, and Revive.
|
||||
- Improve error handling when loading spawn-sets to ensure invalid configurations don't crash the server.
|
||||
@@ -427,6 +430,7 @@
|
||||
- Prevent summary stats tab from making sounds when clicking on an already open tab.
|
||||
- Fixed display case not being able to be fed items from underneath.
|
||||
- Fixed Pokémon battling in water continuously sinking to the bottom.
|
||||
- Fixed passive healing and wake from faint not disabling when their config values are set to 0.
|
||||
|
||||
### Developer
|
||||
- `SpawnCause` is now an implementation of `SpawningInfluence`.
|
||||
@@ -458,6 +462,7 @@
|
||||
- Added HealingSource, an interface applied to all sources of healing from player actions, for easier tracking of healing sources.
|
||||
- Move Change
|
||||
- Shiny Chance Calculation Event (with player context)
|
||||
- Dex Information Changed; this event is fired when the Pokédex is updated with new information.
|
||||
- Rebuilt large swaths of the model animation code to simplify it.
|
||||
- Renamed a bunch of things from %Poseable% to %Posable% because spelling.
|
||||
- Renamed StatelessAnimation to PoseAnimation.
|
||||
@@ -486,6 +491,10 @@
|
||||
- Added support for conditional pose animations.
|
||||
- Added a new universal locator called "top".
|
||||
- Added `eggs_collected` and `eggs_hatched` Advancement triggers.
|
||||
- Added missing `minYaw` configuration to the `q.look()` function for JSON posers.
|
||||
- Some pose condition names have been changed:
|
||||
- `isTouchingWaterOrRain` has been changed to `isInWaterOrRain`
|
||||
- `isSubermegedInWater` has been changed to `isUnderWater`
|
||||
|
||||
### Localization
|
||||
- Updated translations for:
|
||||
@@ -1720,6 +1729,7 @@ Thank you so much to all of our community translators that bring the mod to the
|
||||
- Lowered spawn rate of Tauros.
|
||||
- Sableye now spawns near gem ores as well as amethyst.
|
||||
- Added evolution stones and items to item tags
|
||||
- Pokémon now play their cry animations when clicked on the starter selection screen.
|
||||
|
||||
### Fixes
|
||||
- Fixed catch rates being entirely too difficult.
|
||||
|
||||
@@ -56,6 +56,7 @@ object CobblemonCommands {
|
||||
AbandonMultiTeam.register(dispatcher)
|
||||
FreezePokemonCommand.register(dispatcher)
|
||||
ApplyPlayerTextureCommand.register(dispatcher)
|
||||
RunMolangScriptCommand.register(dispatcher)
|
||||
|
||||
// Possibly lock down registration if and only if under dev environment or running in an environment
|
||||
// with a certain system environment variable set
|
||||
|
||||
@@ -48,6 +48,8 @@ object CobblemonFlows : DataRegistry {
|
||||
val flows = hashMapOf<ResourceLocation, MutableList<ExpressionLike>>()
|
||||
|
||||
override fun reload(manager: ResourceManager) {
|
||||
clientFlows.clear()
|
||||
flows.clear()
|
||||
val folderBeforeNameRegex = ".*\\/([^\\/]+)\\/[^\\/]+\$".toRegex()
|
||||
manager.listResources("flows") { path -> path.endsWith(CobblemonScripts.MOLANG_EXTENSION) }.forEach { (identifier, resource) ->
|
||||
resource.openAsReader().use { stream ->
|
||||
|
||||
@@ -54,6 +54,9 @@ object CobblemonItems : PlatformRegistry<Registry<Item>, ResourceKey<Registry<It
|
||||
override val registry: Registry<Item> = BuiltInRegistries.ITEM
|
||||
override val resourceKey: ResourceKey<Registry<Item>> = Registries.ITEM
|
||||
|
||||
@JvmField
|
||||
val NPC_EDITOR = create("npc_editor", CobblemonItem(Item.Properties().stacksTo(1)))
|
||||
|
||||
@JvmField
|
||||
val pokeBalls = mutableListOf<PokeBallItem>()
|
||||
@JvmField
|
||||
|
||||
@@ -55,6 +55,8 @@ object CobblemonCriteria : PlatformRegistry<Registry<CriterionTrigger<*>>, Resou
|
||||
|
||||
val CAST_POKE_ROD = this.create("cast_poke_rod", SimpleCriterionTrigger(CastPokeRodCriterionCondition.CODEC))
|
||||
|
||||
val REEL_IN_POKEMON = this.create("reel_in_pokemon", SimpleCriterionTrigger(ReelInPokemonCriterionCondition.CODEC))
|
||||
|
||||
// Advancement criteria for [grow_tumblestone.json]
|
||||
val PLANT_TUMBLESTONE = this.create("plant_tumblestone", SimpleCriterionTrigger(PlantTumblestoneCriterion.CODEC))
|
||||
|
||||
|
||||
+14
-10
@@ -8,26 +8,30 @@
|
||||
|
||||
package com.cobblemon.mod.common.advancement.criterion
|
||||
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.codecs.PrimitiveCodec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import java.util.Optional
|
||||
import net.minecraft.advancements.critereon.ContextAwarePredicate
|
||||
import net.minecraft.advancements.critereon.EntityPredicate
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
class CastPokeRodContext(val baitId: ResourceLocation)
|
||||
|
||||
class CastPokeRodCriterionCondition(
|
||||
playerCtx: Optional<ContextAwarePredicate>,
|
||||
val hasBait: Boolean
|
||||
): SimpleCriterionCondition<Boolean>(playerCtx) {
|
||||
playerCtx: Optional<ContextAwarePredicate>,
|
||||
val baitId: String
|
||||
): SimpleCriterionCondition<CastPokeRodContext>(playerCtx) {
|
||||
|
||||
companion object {
|
||||
val CODEC: Codec<CastPokeRodCriterionCondition> = RecordCodecBuilder.create { it.group(
|
||||
EntityPredicate.ADVANCEMENT_CODEC.optionalFieldOf("player").forGetter(CastPokeRodCriterionCondition::playerCtx),
|
||||
PrimitiveCodec.BOOL.fieldOf("hasBait").forGetter(CastPokeRodCriterionCondition::hasBait)
|
||||
).apply(it, ::CastPokeRodCriterionCondition) }
|
||||
EntityPredicate.ADVANCEMENT_CODEC.optionalFieldOf("player").forGetter(CastPokeRodCriterionCondition::playerCtx),
|
||||
Codec.STRING.optionalFieldOf("baitId", "empty_bait").forGetter(CastPokeRodCriterionCondition::baitId)
|
||||
).apply(it, { playerCtx, baitId -> CastPokeRodCriterionCondition(playerCtx, baitId.ifEmpty { "empty_bait" }) }) }
|
||||
}
|
||||
|
||||
override fun matches(player: ServerPlayer, context: Boolean): Boolean {
|
||||
return hasBait == context
|
||||
override fun matches(player: ServerPlayer, context: CastPokeRodContext): Boolean {
|
||||
return (context.baitId == this.baitId.asIdentifierDefaultingNamespace() || this.baitId.equals("empty_bait"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.advancement.criterion
|
||||
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import java.util.Optional
|
||||
import net.minecraft.advancements.critereon.ContextAwarePredicate
|
||||
import net.minecraft.advancements.critereon.EntityPredicate
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
class ReelInPokemonContext(val pokemonId : ResourceLocation, val baitId: ResourceLocation)
|
||||
|
||||
class ReelInPokemonCriterionCondition(
|
||||
playerCtx: Optional<ContextAwarePredicate>,
|
||||
val pokemonId: String,
|
||||
val baitId: String
|
||||
) : SimpleCriterionCondition<ReelInPokemonContext>(playerCtx) {
|
||||
|
||||
companion object {
|
||||
val CODEC: Codec<ReelInPokemonCriterionCondition> = RecordCodecBuilder.create { it.group(
|
||||
EntityPredicate.ADVANCEMENT_CODEC.optionalFieldOf("player").forGetter { it.playerCtx },
|
||||
Codec.STRING.optionalFieldOf("pokemonId", "any").forGetter { it.pokemonId },
|
||||
Codec.STRING.optionalFieldOf("baitId", "empty_bait").forGetter { it.baitId }
|
||||
).apply(it, { playerCtx, pokemonId, baitId -> ReelInPokemonCriterionCondition(playerCtx, pokemonId, baitId.ifEmpty { "empty_bait" }) }) }
|
||||
}
|
||||
|
||||
override fun matches(player: ServerPlayer, context: ReelInPokemonContext): Boolean {
|
||||
return (context.pokemonId == this.pokemonId.asIdentifierDefaultingNamespace() || this.pokemonId == "any") && (context.baitId == this.baitId.asIdentifierDefaultingNamespace() || this.baitId == "empty_bait")
|
||||
}
|
||||
}
|
||||
@@ -192,6 +192,8 @@ object CobblemonEvents {
|
||||
val POKEMON_GAINED = EventObservable<PokemonGainedEvent>()
|
||||
@JvmField
|
||||
val POKEMON_SEEN = EventObservable<PokemonSeenEvent>()
|
||||
@JvmField
|
||||
val POKEDEX_DATA_CHANGED = EventObservable<PokedexDataChangedEvent>()
|
||||
|
||||
// Fishing
|
||||
@JvmField
|
||||
|
||||
+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.api.events.pokemon
|
||||
|
||||
import com.bedrockk.molang.runtime.value.DoubleValue
|
||||
import com.bedrockk.molang.runtime.value.MoValue
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.asMoLangValue
|
||||
import com.cobblemon.mod.common.api.pokedex.FormDexRecord
|
||||
import com.cobblemon.mod.common.api.pokedex.PokedexEntryProgress
|
||||
import com.cobblemon.mod.common.api.pokedex.AbstractPokedexManager
|
||||
import com.cobblemon.mod.common.pokedex.scanner.PokedexEntityData
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.getPlayer
|
||||
import com.mojang.datafixers.util.Either
|
||||
import java.util.UUID
|
||||
|
||||
/**
|
||||
* Event that fires when a Pokémon's information is gained or updated in the Pokédex.
|
||||
*/
|
||||
data class PokedexDataChangedEvent(
|
||||
val dataSource: Either<PokedexEntityData, Pokemon>,
|
||||
val knowledge: PokedexEntryProgress,
|
||||
val playerUUID: UUID,
|
||||
val record: FormDexRecord
|
||||
) {
|
||||
val pokedexManager: AbstractPokedexManager
|
||||
get() = record.speciesDexRecord.pokedexManager
|
||||
|
||||
val context = mutableMapOf<String, MoValue>(
|
||||
"player" to (playerUUID.getPlayer()?.asMoLangValue() ?: DoubleValue.ZERO),
|
||||
"pokemon" to dataSource.map({ DoubleValue.ZERO }, { it.struct }),
|
||||
"data" to dataSource.map({ it.struct }, { DoubleValue.ZERO }),
|
||||
"knowledge" to StringValue(knowledge.name.lowercase()),
|
||||
"pokedex" to pokedexManager.struct
|
||||
)
|
||||
}
|
||||
+1
-2
@@ -14,5 +14,4 @@ import java.util.UUID
|
||||
data class PokemonGainedEvent(
|
||||
val playerId: UUID,
|
||||
val pokemon: Pokemon
|
||||
) {
|
||||
}
|
||||
)
|
||||
+1
-3
@@ -9,11 +9,9 @@
|
||||
package com.cobblemon.mod.common.api.events.pokemon
|
||||
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import java.util.UUID
|
||||
|
||||
data class PokemonSeenEvent(
|
||||
val playerId: UUID,
|
||||
val pokemon: Pokemon
|
||||
) {
|
||||
}
|
||||
)
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.gui
|
||||
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import net.minecraft.client.gui.components.AbstractWidget
|
||||
import net.minecraft.client.gui.components.Renderable
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener
|
||||
@@ -22,7 +23,7 @@ abstract class ParentWidget(
|
||||
pX: Int, pY: Int,
|
||||
pWidth: Int, pHeight: Int,
|
||||
component: Component
|
||||
): Renderable, AbstractWidget(pX, pY, pWidth, pHeight, component) {
|
||||
): CobblemonRenderable, AbstractWidget(pX, pY, pWidth, pHeight, component) {
|
||||
|
||||
val children: MutableList<GuiEventListener> = mutableListOf()
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.item.ability
|
||||
|
||||
import com.cobblemon.mod.common.api.Priority
|
||||
import com.cobblemon.mod.common.api.abilities.*
|
||||
import com.cobblemon.mod.common.item.interactive.ability.AbilityTypeChanger
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
@@ -33,7 +34,7 @@ interface AbilityChanger<T : PotentialAbility> {
|
||||
* @param pokemon The [Pokemon] being queried.
|
||||
* @return A set containing all their legal abilities associated with [type], can be empty.
|
||||
*/
|
||||
fun queryPossible(pokemon: Pokemon): Set<AbilityTemplate>
|
||||
fun queryPossible(pokemon: Pokemon): Set<Pair<AbilityTemplate, Priority>>
|
||||
|
||||
/**
|
||||
* Attempts to update the ability of the given [pokemon].
|
||||
|
||||
@@ -29,6 +29,13 @@ import com.cobblemon.mod.common.api.dialogue.ReferenceDialogueFaceProvider
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffectContext
|
||||
import com.cobblemon.mod.common.api.moves.animations.ActionEffects
|
||||
import com.cobblemon.mod.common.api.moves.animations.NPCProvider
|
||||
import com.cobblemon.mod.common.api.pokedex.AbstractPokedexManager
|
||||
import com.cobblemon.mod.common.api.pokedex.CaughtCount
|
||||
import com.cobblemon.mod.common.api.pokedex.CaughtPercent
|
||||
import com.cobblemon.mod.common.api.pokedex.PokedexEntryProgress
|
||||
import com.cobblemon.mod.common.api.pokedex.PokedexManager
|
||||
import com.cobblemon.mod.common.api.pokedex.SeenCount
|
||||
import com.cobblemon.mod.common.api.pokedex.SeenPercent
|
||||
import com.cobblemon.mod.common.api.pokemon.stats.Stats
|
||||
import com.cobblemon.mod.common.api.scripting.CobblemonScripts
|
||||
import com.cobblemon.mod.common.api.spawning.context.SpawningContext
|
||||
@@ -50,6 +57,7 @@ import com.cobblemon.mod.common.entity.pokemon.ai.PokemonMoveControl
|
||||
import com.cobblemon.mod.common.net.messages.client.animation.PlayPosableAnimationPacket
|
||||
import com.cobblemon.mod.common.net.messages.client.effect.RunPosableMoLangPacket
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.pokemon.Species
|
||||
import com.cobblemon.mod.common.util.*
|
||||
import com.mojang.datafixers.util.Either
|
||||
import java.util.UUID
|
||||
@@ -102,6 +110,12 @@ object MoLangFunctions {
|
||||
val message = params.get<MoValue>(0).asString()
|
||||
Cobblemon.LOGGER.info(message)
|
||||
},
|
||||
"set_query" to java.util.function.Function { params ->
|
||||
val variable = params.getString(0)
|
||||
val value = params.get<MoValue>(1)
|
||||
params.environment.query.addFunction(variable) { value }
|
||||
return@Function value
|
||||
},
|
||||
"replace" to java.util.function.Function { params ->
|
||||
val text = params.getString(0)
|
||||
val search = params.getString(1)
|
||||
@@ -320,6 +334,8 @@ object MoLangFunctions {
|
||||
val data = Cobblemon.molangData.load(player.uuid)
|
||||
if (data.map.containsKey(npcId)) {
|
||||
return@put (data.map[npcId] as VariableStruct).map[variable] ?: DoubleValue.ZERO
|
||||
} else {
|
||||
return@put DoubleValue.ZERO
|
||||
}
|
||||
}
|
||||
map.put("set_npc_variable") { params ->
|
||||
@@ -328,16 +344,14 @@ object MoLangFunctions {
|
||||
val value = params.get<MoValue>(2)
|
||||
val saveAfterwards = params.getBooleanOrNull(3) != false
|
||||
val data = Cobblemon.molangData.load(player.uuid)
|
||||
if (data.map.containsKey(npcId)) {
|
||||
(data.map[npcId] as VariableStruct).map[variable] = value
|
||||
if (saveAfterwards) {
|
||||
Cobblemon.molangData.save(player.uuid)
|
||||
}
|
||||
return@put DoubleValue.ONE
|
||||
} else {
|
||||
return@put DoubleValue.ZERO
|
||||
val npcData = data.map.getOrPut(npcId) { VariableStruct() } as VariableStruct
|
||||
npcData.map[variable] = value
|
||||
if (saveAfterwards) {
|
||||
Cobblemon.molangData.save(player.uuid)
|
||||
}
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map.put("pokedex") { player.pokedex().struct }
|
||||
}
|
||||
map
|
||||
}
|
||||
@@ -594,6 +608,7 @@ object MoLangFunctions {
|
||||
}
|
||||
map.put("is_wild") { DoubleValue(pokemon.entity?.let { it.ownerUUID == null } == true) }
|
||||
map.put("is_shiny") { DoubleValue(pokemon.shiny) }
|
||||
map.put("species") { pokemon.species.struct }
|
||||
map.put("form") { StringValue(pokemon.form.name) }
|
||||
map.put("weight") { DoubleValue(pokemon.species.weight.toDouble()) }
|
||||
map.put("matches") { params -> DoubleValue(params.getString(0).toProperties().matches(pokemon)) }
|
||||
@@ -804,6 +819,78 @@ object MoLangFunctions {
|
||||
}
|
||||
)
|
||||
|
||||
val pokedexFunctions: MutableList<(AbstractPokedexManager) -> HashMap<String, java.util.function.Function<MoParams, Any>>> = mutableListOf(
|
||||
{ pokedex ->
|
||||
val map = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
|
||||
map.put("get_species_record") { params ->
|
||||
val speciesId = params.getString(0).asIdentifierDefaultingNamespace()
|
||||
pokedex.speciesRecords[speciesId]?.struct ?: QueryStruct(hashMapOf())
|
||||
}
|
||||
|
||||
map.put("has_seen") { params ->
|
||||
val speciesId = params.getString(0).asIdentifierDefaultingNamespace()
|
||||
val formName = params.getStringOrNull(1)
|
||||
|
||||
if (formName == null) {
|
||||
return@put DoubleValue(pokedex.getHighestKnowledgeForSpecies(speciesId).ordinal >= PokedexEntryProgress.ENCOUNTERED.ordinal)
|
||||
} else {
|
||||
return@put DoubleValue((pokedex.getSpeciesRecord(speciesId)?.getFormRecord(formName)?.knowledge?.ordinal ?: 0) >= PokedexEntryProgress.ENCOUNTERED.ordinal)
|
||||
}
|
||||
}
|
||||
|
||||
map.put("has_caught") { params ->
|
||||
val speciesId = params.getString(0).asIdentifierDefaultingNamespace()
|
||||
val formName = params.getStringOrNull(1)
|
||||
if (formName == null) {
|
||||
return@put DoubleValue(pokedex.getHighestKnowledgeForSpecies(speciesId) == PokedexEntryProgress.CAUGHT)
|
||||
} else {
|
||||
return@put DoubleValue(pokedex.getSpeciesRecord(speciesId)?.getFormRecord(formName)?.knowledge == PokedexEntryProgress.CAUGHT)
|
||||
}
|
||||
}
|
||||
map.put("caught_count") { DoubleValue(pokedex.getGlobalCalculatedValue(CaughtCount)) }
|
||||
map.put("seen_count") { DoubleValue(pokedex.getGlobalCalculatedValue(SeenCount)) }
|
||||
map.put("caught_percent") { DoubleValue(pokedex.getGlobalCalculatedValue(CaughtPercent)) }
|
||||
map.put("seen_percent") { DoubleValue(pokedex.getGlobalCalculatedValue(SeenPercent)) }
|
||||
|
||||
if (pokedex is PokedexManager) {
|
||||
map.put("player_id") { StringValue(pokedex.uuid.toString()) }
|
||||
map.put("see") { params ->
|
||||
val pokemon = params.get<ObjectValue<Pokemon>>(0).obj
|
||||
pokedex.encounter(pokemon)
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
map.put("catch") { params ->
|
||||
val pokemon = params.get<ObjectValue<Pokemon>>(0).obj
|
||||
pokedex.catch(pokemon)
|
||||
return@put DoubleValue.ONE
|
||||
}
|
||||
}
|
||||
|
||||
map
|
||||
}
|
||||
)
|
||||
|
||||
val speciesFunctions: MutableList<(Species) -> HashMap<String, java.util.function.Function<MoParams, Any>>> = mutableListOf(
|
||||
{ species ->
|
||||
val map = hashMapOf<String, java.util.function.Function<MoParams, Any>>()
|
||||
|
||||
map.put("identifier") { StringValue(species.resourceIdentifier.toString()) }
|
||||
map.put("name") { StringValue(species.name) }
|
||||
map.put("primary_type") { StringValue(species.primaryType.name) }
|
||||
map.put("secondary_type") { StringValue(species.secondaryType?.name ?: "null") }
|
||||
map.put("experience_group") { StringValue(species.experienceGroup.name) }
|
||||
map.put("height") { DoubleValue(species.height) }
|
||||
map.put("weight") { DoubleValue(species.weight) }
|
||||
map.put("base_scale") { DoubleValue(species.baseScale) }
|
||||
map.put("hitbox_width") { DoubleValue(species.hitbox.width) }
|
||||
map.put("hitbox_height") { DoubleValue(species.hitbox.height) }
|
||||
map.put("hitbox_fixed") { DoubleValue(species.hitbox.fixed) }
|
||||
map.put("catch_rate") { DoubleValue(species.catchRate) }
|
||||
|
||||
map
|
||||
}
|
||||
)
|
||||
|
||||
fun Holder<Biome>.asBiomeMoLangValue() = asMoLangValue(Registries.BIOME).addFunctions(biomeFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap())
|
||||
fun Holder<Level>.asWorldMoLangValue() = asMoLangValue(Registries.DIMENSION).addFunctions(worldFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap())
|
||||
fun Holder<Block>.asBlockMoLangValue() = asMoLangValue(Registries.BLOCK).addFunctions(blockFunctions.flatMap { it(this).entries.map { it.key to it.value } }.toMap())
|
||||
@@ -935,6 +1022,22 @@ object MoLangFunctions {
|
||||
return this
|
||||
}
|
||||
|
||||
fun QueryStruct.addPokedexFunctions(pokedexManager: AbstractPokedexManager): QueryStruct {
|
||||
val addedFunctions = pokedexFunctions
|
||||
.flatMap { it.invoke(pokedexManager).entries }
|
||||
.associate { it.key to it.value }
|
||||
functions.putAll(addedFunctions)
|
||||
return this
|
||||
}
|
||||
|
||||
fun QueryStruct.addSpeciesFunctions(species: Species): QueryStruct {
|
||||
val addedFunctions = speciesFunctions
|
||||
.flatMap { it.invoke(species).entries }
|
||||
.associate { it.key to it.value }
|
||||
functions.putAll(addedFunctions)
|
||||
return this
|
||||
}
|
||||
|
||||
fun QueryStruct.addPokemonFunctions(pokemon: Pokemon): QueryStruct {
|
||||
val addedFunctions = pokemonFunctions
|
||||
.flatMap { it.invoke(pokemon).entries }
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.moves
|
||||
|
||||
enum class MoveEffectiveness(val showdownId: Int, val multiplier: Double) {
|
||||
NORMAL(0, 1.0),
|
||||
WEAKNESS(1, 2.0),
|
||||
RESISTANCE(2, 0.5),
|
||||
IMMUNITY(3, 0.0);
|
||||
|
||||
companion object {
|
||||
fun of(showdownId: Int): MoveEffectiveness {
|
||||
return entries.find { it.showdownId == showdownId }
|
||||
?: throw IllegalArgumentException("Unknown MoveEffectiveness: $showdownId")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.api.moves
|
||||
|
||||
import com.cobblemon.mod.common.api.types.ElementalType
|
||||
import com.cobblemon.mod.common.api.types.ElementalTypes
|
||||
import com.cobblemon.mod.common.battles.runner.ShowdownService
|
||||
|
||||
object TypeChart {
|
||||
private val movesEffectiveness = mutableMapOf<ElementalType, MutableMap<ElementalType, MoveEffectiveness>>()
|
||||
|
||||
fun load() {
|
||||
movesEffectiveness.clear()
|
||||
|
||||
val typeChartJson = ShowdownService.service.getTypeChart()
|
||||
typeChartJson.keySet().forEach { type ->
|
||||
val defenderType = ElementalTypes.get(type) ?: return@forEach
|
||||
|
||||
val moveTypes = typeChartJson.get(type).asJsonObject.get("damageTaken").asJsonObject
|
||||
moveTypes.keySet().forEach innerLoop@ {
|
||||
val moveType = ElementalTypes.get(it) ?: return@innerLoop
|
||||
val moveEffectiveness = moveTypes.get(it).asInt
|
||||
|
||||
val defenderMap = movesEffectiveness.getOrPut(moveType) { mutableMapOf() }
|
||||
defenderMap[defenderType] = MoveEffectiveness.of(moveEffectiveness)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getMoveEffectiveness(moveType: ElementalType, defenderTypes: List<ElementalType?>): Double {
|
||||
var multiplier = 1.0
|
||||
defenderTypes.filterNotNull().forEach {
|
||||
multiplier *= getMoveEffectiveness(moveType, it).multiplier
|
||||
}
|
||||
|
||||
return multiplier
|
||||
}
|
||||
|
||||
private fun getMoveEffectiveness(moveType: ElementalType, defenderType: ElementalType): MoveEffectiveness {
|
||||
return movesEffectiveness[moveType]?.get(defenderType) ?: throw IllegalArgumentException("Unknown effectiveness type: $moveType $defenderType")
|
||||
}
|
||||
}
|
||||
@@ -38,7 +38,8 @@ class NPCClass {
|
||||
var resourceIdentifier: ResourceLocation = cobblemonResource("dummy")
|
||||
var names: MutableList<Component> = mutableListOf()
|
||||
var aspects: MutableSet<String> = mutableSetOf() // These only make sense when applied via presets
|
||||
var hitbox = EntityDimensions.scalable(0.6F, 1.8F)
|
||||
var hitbox = EntityDimensions.scalable(0.6F, 1.8F).withEyeHeight(1.62F)
|
||||
var modelScale: Float = 0.94F
|
||||
var battleConfiguration = NPCBattleConfiguration()
|
||||
var interaction: NPCInteractConfiguration? = null
|
||||
var canDespawn = true
|
||||
@@ -48,6 +49,7 @@ class NPCClass {
|
||||
var party: NPCPartyProvider? = null
|
||||
var skill: Int = 0
|
||||
var autoHealParty: Boolean = true
|
||||
var randomizePartyOrder: Boolean = false
|
||||
var battleTheme: ResourceLocation? = null
|
||||
var ai: MutableList<BrainConfig> = mutableListOf()
|
||||
var isMovable: Boolean = true
|
||||
@@ -83,6 +85,7 @@ class NPCClass {
|
||||
}
|
||||
buffer.writeInt(skill)
|
||||
buffer.writeBoolean(autoHealParty)
|
||||
buffer.writeBoolean(randomizePartyOrder)
|
||||
buffer.writeMapK(size = IntSize.U_BYTE, map = variables) { (key, value) ->
|
||||
buffer.writeString(key)
|
||||
buffer.writeString(value.asString())
|
||||
@@ -127,6 +130,7 @@ class NPCClass {
|
||||
}.toMutableList()
|
||||
skill = buffer.readInt()
|
||||
autoHealParty = buffer.readBoolean()
|
||||
randomizePartyOrder = buffer.readBoolean()
|
||||
buffer.readMapK(size = IntSize.U_BYTE, map = variables) {
|
||||
val key = buffer.readString()
|
||||
val value = buffer.readString()
|
||||
|
||||
@@ -30,6 +30,7 @@ class NPCPreset {
|
||||
var ai: List<BrainConfig>? = null
|
||||
var skill: Int? = null
|
||||
var autoHealParty: Boolean? = null
|
||||
var randomizePartyOrder: Boolean? = null
|
||||
var battleTheme: ResourceLocation? = null
|
||||
var isMovable: Boolean? = null
|
||||
var isInvulnerable: Boolean? = null
|
||||
@@ -53,6 +54,7 @@ class NPCPreset {
|
||||
hitbox?.let { npcClass.hitbox = it }
|
||||
skill?.let { npcClass.skill = it }
|
||||
autoHealParty?.let { npcClass.autoHealParty = it }
|
||||
randomizePartyOrder?.let { npcClass.randomizePartyOrder = it }
|
||||
battleTheme?.let { npcClass.battleTheme = it }
|
||||
ai?.let { npcClass.ai.addAll(it) }
|
||||
isMovable?.let { npcClass.isMovable = it }
|
||||
|
||||
@@ -77,6 +77,7 @@ any number of presets and the properties of those presets will be merged into th
|
||||
"canDespawn": false,
|
||||
"skill": 5,
|
||||
"autoHealParty": true,
|
||||
"randomizePartyOrder": true,
|
||||
"party": {
|
||||
"type": "simple",
|
||||
"pokemon": [
|
||||
@@ -282,15 +283,20 @@ is not mentioned in the Pokémon properties will be set to the seed level.
|
||||
The "pool" party type is a way to define a party of Pokémon using a more complicated format that involves some
|
||||
randomization and weighting to different Pokémon options.
|
||||
|
||||
A pool party provider can be static or dynamic depending on the value of `isStatic`. It specifies the minimum
|
||||
and maximum number of Pokémon that can be in the party using `minPokemon` and `maxPokemon`. The `pool` property dictates all of the possible Pokémon, with
|
||||
each being an object with several properties.
|
||||
A pool party provider can be static or dynamic depending on the value of `isStatic`. If `useFixedRandom` is true, the Pokémon it selects
|
||||
from the pool will be constant for a single spawned NPC entity. This is slightly different to a static party because
|
||||
the level of the Pokémon can still be modified dynamically using MoLang values inside each entry's `level` field.
|
||||
|
||||
The pool specifies the minimum and maximum number of Pokémon that can be in the party using `minPokemon` and `maxPokemon`.
|
||||
|
||||
The `pool` property dictates all the possible Pokémon with each being an object with several properties.
|
||||
|
||||
- The `pokemon` property is the Pokémon properties as used in commands and spawn files that will generate the Pokémon.
|
||||
- The `weight` property is a decimal number that represents how likely that Pokémon is to be chosen. If the weight is -1, it will be guaranteed to be selected. Defaults to 1. The larger the value, the more likely it will be chosen.
|
||||
- The `selectableTimes` property is the maximum number of times that the entry can be selected in the party. Defaults to 1.
|
||||
- The `npcLevels` property is a range of seed levels that the Pokémon can be generated at. For example, if the NPC is spawned with seed level 10, and the range is 5-9, the Pokémon will not be selected. The actual level of the Pokémon will be the seed level. Defaults to "1-100".
|
||||
- The `levelVariation` property is the amount of variation the Pokémon's level can have from the NPC seed level. For example, a value of 2 will mean that for an NPC generated with seed level 10, the Pokémon will be generated somewhere between level 8 and 12 inclusive. Defaults to zero.
|
||||
- The `level` property can be used instead of `levelVariation` to force a specific level. This is a MoLang expression.
|
||||
|
||||
For `minPokemon`, `maxPokemon`, `weight`, `selectableTimes`, and `levelVariation`, the values can be a simple number or be full MoLang expressions. At the time
|
||||
of seeding an NPC, the cosmetic variations have already been applied. Therefore, it's possible to make these properties
|
||||
@@ -306,7 +312,8 @@ a single battle challenge and this is a dynamic party, there will also be a `q.p
|
||||
"type": "pool",
|
||||
"minPokemon": "3",
|
||||
"maxPokemon": "6",
|
||||
"isStatic": true,
|
||||
"isStatic": false,
|
||||
"useFixedRandom": true,
|
||||
"pool": [
|
||||
{
|
||||
"pokemon": "weedle",
|
||||
@@ -343,7 +350,9 @@ a single battle challenge and this is a dynamic party, there will also be a `q.p
|
||||
"pokemon": "butterfree",
|
||||
"weight": "5",
|
||||
"npcLevels": "10-15",
|
||||
"selectableTimes": "1"
|
||||
"selectableTimes": "1",
|
||||
"level": "q.player.party.highest_level"
|
||||
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -395,6 +404,11 @@ the NPC and move them using leads.
|
||||
Controls whether the NPC can be hit by projectiles. Disabling this option prevents unwanted
|
||||
interactions, such as players moving the NPC with fishing rods or other projectiles.
|
||||
|
||||
### randomizePartyOrder
|
||||
Whether the NPC's party order will be randomized between battles. When true, this NPC's party (regardless of
|
||||
whether it was dynamic or static) will choose its initial send-out Pokémon randomly instead of always choosing the first
|
||||
Pokémon in the party.
|
||||
|
||||
### ai
|
||||
The AI property is an array of brain configurations. This is used to configure the behaviours of the NPC. See
|
||||
the documentation for brain configurations at [AI Configuration](../ai/config/README.md).
|
||||
+19
-11
@@ -26,6 +26,7 @@ import com.cobblemon.mod.common.util.withQueryValue
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonPrimitive
|
||||
import kotlin.random.Random
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
|
||||
/**
|
||||
@@ -50,6 +51,7 @@ class PoolPartyProvider : NPCPartyProvider {
|
||||
override val type = TYPE
|
||||
|
||||
override var isStatic: Boolean = false
|
||||
var useFixedRandom: Boolean = false
|
||||
var minPokemon: Expression = "1".asExpression()
|
||||
var maxPokemon: Expression = "6".asExpression()
|
||||
var pool = mutableListOf<DynamicPokemon>()
|
||||
@@ -63,6 +65,7 @@ class PoolPartyProvider : NPCPartyProvider {
|
||||
return@map DynamicPokemon(
|
||||
PokemonProperties.parse(it.asString),
|
||||
"0".asExpression(),
|
||||
null,
|
||||
1..100,
|
||||
"1".asExpression(),
|
||||
"1".asExpression()
|
||||
@@ -71,19 +74,22 @@ class PoolPartyProvider : NPCPartyProvider {
|
||||
|
||||
it as JsonObject
|
||||
DynamicPokemon(
|
||||
PokemonProperties.parse(it.getAsJsonPrimitive("pokemon").asString),
|
||||
it.getAsJsonPrimitive("levelVariation")?.asString?.asExpression() ?: "0".asExpression(),
|
||||
it.getAsJsonPrimitive("npcLevels")?.asString?.split("-")?.let { it[0].toInt()..it[1].toInt() } ?: 1..100,
|
||||
it.getAsJsonPrimitive("selectableTimes")?.asString?.asExpression() ?: "1".asExpression(),
|
||||
it.getAsJsonPrimitive("weight")?.asString?.asExpression() ?: "1".asExpression()
|
||||
PokemonProperties.parse(it.get("pokemon").asString),
|
||||
it.get("levelVariation")?.asString?.asExpression() ?: "0".asExpression(),
|
||||
it.get("level")?.asString?.asExpression(),
|
||||
it.get("npcLevels")?.asString?.split("-")?.let { it[0].toInt()..it[1].toInt() } ?: 1..100,
|
||||
it.get("selectableTimes")?.asString?.asExpression() ?: "1".asExpression(),
|
||||
it.get("weight")?.asString?.asExpression() ?: "1".asExpression()
|
||||
)
|
||||
}.toMutableList()
|
||||
isStatic = json.getAsJsonPrimitive("isStatic").asBoolean
|
||||
isStatic = json.get("isStatic").asBoolean
|
||||
json.get("useFixedRandom")?.asBoolean?.let { useFixedRandom = it }
|
||||
}
|
||||
|
||||
class DynamicPokemon(
|
||||
val pokemon: PokemonProperties,
|
||||
val levelVariation: Expression,
|
||||
val level: Expression? = null,
|
||||
val npcLevels: IntRange,
|
||||
val selectableTimes: Expression,
|
||||
val weight: Expression = "1".asExpression()
|
||||
@@ -99,6 +105,7 @@ class PoolPartyProvider : NPCPartyProvider {
|
||||
|
||||
fun formulateParty(npc: NPCEntity, level: Int, players: List<ServerPlayer>, party: NPCPartyStore) {
|
||||
val runtime = MoLangRuntime().setup().withQueryValue("npc", npc.struct)
|
||||
val random = if (useFixedRandom) Random(npc.uuid.hashCode()) else Random.Default
|
||||
runtime.withQueryValue("level", DoubleValue(level))
|
||||
runtime.withQueryValue("players", players.asArrayValue { it.asMoLangValue() })
|
||||
if (players.size == 1) {
|
||||
@@ -107,14 +114,14 @@ class PoolPartyProvider : NPCPartyProvider {
|
||||
}
|
||||
val minPokemon = runtime.resolveInt(this.minPokemon)
|
||||
val maxPokemon = runtime.resolveInt(this.maxPokemon)
|
||||
var desiredPokemonCount = (minPokemon..maxPokemon).random()
|
||||
var desiredPokemonCount = (minPokemon..maxPokemon).random(random)
|
||||
|
||||
val workingPool = pool.filter { level in it.npcLevels && runtime.resolveInt(it.selectableTimes) > 0 }.toMutableList()
|
||||
val useCounts = mutableMapOf<DynamicPokemon, Int>()
|
||||
|
||||
while (desiredPokemonCount > 0 && workingPool.any { it.hasWeight(runtime) }) {
|
||||
val selected = workingPool.filter { it.getWeight(runtime) == -1F }.randomOrNull()
|
||||
?: workingPool.weightedSelection { it.getWeight(runtime) }
|
||||
val selected = workingPool.filter { it.getWeight(runtime) == -1F }.randomOrNull(random)
|
||||
?: workingPool.weightedSelection(random = random) { it.getWeight(runtime) }
|
||||
?: break
|
||||
useCounts[selected] = useCounts.getOrDefault(selected, 0) + 1
|
||||
val allowedSelections = runtime.resolveInt(selected.selectableTimes)
|
||||
@@ -124,9 +131,10 @@ class PoolPartyProvider : NPCPartyProvider {
|
||||
desiredPokemonCount--
|
||||
|
||||
// If the Pokémon's props specifies a level then use that, otherwise choose a random level within the range
|
||||
val levelVariation = (0..runtime.resolveInt(selected.levelVariation)).random()
|
||||
val levelVariation = (0..runtime.resolveInt(selected.levelVariation)).random(random)
|
||||
val randomLevel = level + levelVariation
|
||||
val instance = selected.pokemon.copy().also { it.level = it.level ?: randomLevel }.create()
|
||||
val dictatedLevel = selected.level?.let { runtime.resolveInt(it) }
|
||||
val instance = selected.pokemon.copy().also { it.level = it.level ?: dictatedLevel ?: randomLevel }.create()
|
||||
party.add(instance)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -32,5 +32,5 @@ class WeightedNPCVariationProvider : NPCVariationProvider {
|
||||
override val aspects: Set<String>
|
||||
get() = options.flatMap(WeightedAspect::aspects).toSet()
|
||||
|
||||
override fun provideAspects(npcEntity: NPCEntity) = options.weightedSelection(WeightedAspect::weight)?.aspects ?: emptySet()
|
||||
override fun provideAspects(npcEntity: NPCEntity) = options.weightedSelection { it.weight }?.aspects ?: emptySet()
|
||||
}
|
||||
@@ -82,6 +82,8 @@ object CobblemonPermissions {
|
||||
|
||||
val ABANDON_MULTITEAM = this.create("${COMMAND_PREFIX}abandonmultiteam", PermissionLevel.NONE)
|
||||
|
||||
val RUN_MOLANG_SCRIPT = this.create("${COMMAND_PREFIX}runmolangscript", PermissionLevel.CHEAT_COMMANDS_AND_COMMAND_BLOCKS)
|
||||
|
||||
fun all(): Iterable<Permission> = this.permissions
|
||||
|
||||
private fun create(node: String, level: PermissionLevel): Permission {
|
||||
|
||||
+5
-7
@@ -8,13 +8,13 @@
|
||||
|
||||
package com.cobblemon.mod.common.api.pokedex
|
||||
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.addPokedexFunctions
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.addStandardFunctions
|
||||
import com.cobblemon.mod.common.api.molang.ObjectValue
|
||||
import com.cobblemon.mod.common.api.pokedex.entry.PokedexEntry
|
||||
import com.cobblemon.mod.common.api.pokedex.entry.PokedexForm
|
||||
import com.cobblemon.mod.common.pokedex.scanner.PokedexEntityData
|
||||
import com.cobblemon.mod.common.pokemon.Gender
|
||||
import com.cobblemon.mod.common.util.asIdentifierDefaultingNamespace
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
abstract class AbstractPokedexManager {
|
||||
@@ -23,11 +23,9 @@ abstract class AbstractPokedexManager {
|
||||
private val globalCalculatedValues = mutableMapOf<GlobalPokedexValueCalculator<*>, Any>()
|
||||
|
||||
@Transient
|
||||
val struct = QueryStruct(hashMapOf()).addStandardFunctions()
|
||||
.addFunction("get_species_record") { params ->
|
||||
val speciesId = params.getString(0).asIdentifierDefaultingNamespace()
|
||||
speciesRecords[speciesId]?.struct ?: QueryStruct(hashMapOf())
|
||||
}
|
||||
val struct = ObjectValue<AbstractPokedexManager>(this)
|
||||
.addStandardFunctions()
|
||||
.addPokedexFunctions(this)
|
||||
|
||||
fun deleteSpeciesRecord(speciesId: ResourceLocation) {
|
||||
speciesRecords.remove(speciesId)
|
||||
|
||||
@@ -11,6 +11,8 @@ package com.cobblemon.mod.common.api.pokedex
|
||||
import com.bedrockk.molang.runtime.struct.QueryStruct
|
||||
import com.bedrockk.molang.runtime.struct.VariableStruct
|
||||
import com.bedrockk.molang.runtime.value.StringValue
|
||||
import com.cobblemon.mod.common.api.events.CobblemonEvents
|
||||
import com.cobblemon.mod.common.api.events.pokemon.PokedexDataChangedEvent
|
||||
import com.cobblemon.mod.common.pokedex.scanner.PokedexEntityData
|
||||
import com.cobblemon.mod.common.pokemon.Gender
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
@@ -19,6 +21,7 @@ import com.cobblemon.mod.common.util.readString
|
||||
import com.cobblemon.mod.common.util.writeEnumConstant
|
||||
import com.cobblemon.mod.common.util.writeString
|
||||
import com.google.common.collect.Sets
|
||||
import com.mojang.datafixers.util.Either
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.codecs.ListCodec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
@@ -123,6 +126,10 @@ class FormDexRecord {
|
||||
}
|
||||
speciesDexRecord.addInformation(pokemon, knowledge)
|
||||
speciesDexRecord.onFormRecordUpdated(this)
|
||||
|
||||
(speciesDexRecord.pokedexManager as? PokedexManager)?.let { pokedexManager ->
|
||||
CobblemonEvents.POKEDEX_DATA_CHANGED.post(PokedexDataChangedEvent(Either.right(pokemon), knowledge, pokedexManager.uuid, this))
|
||||
}
|
||||
}
|
||||
|
||||
private fun addInformation(pokedexEntityData: PokedexEntityData, knowledge: PokedexEntryProgress) {
|
||||
@@ -133,6 +140,10 @@ class FormDexRecord {
|
||||
}
|
||||
speciesDexRecord.addInformation(pokedexEntityData, knowledge)
|
||||
speciesDexRecord.onFormRecordUpdated(this)
|
||||
|
||||
(speciesDexRecord.pokedexManager as? PokedexManager)?.let { pokedexManager ->
|
||||
CobblemonEvents.POKEDEX_DATA_CHANGED.post(PokedexDataChangedEvent(Either.left(pokedexEntityData), knowledge, pokedexManager.uuid, this))
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns whether the given [Pokemon] and [knowledge] would add new information to the Pokédex.*/
|
||||
|
||||
@@ -19,6 +19,7 @@ import com.cobblemon.mod.common.api.drop.ItemDropMethod
|
||||
import com.cobblemon.mod.common.api.entity.EntityDimensionsAdapter
|
||||
import com.cobblemon.mod.common.api.molang.ExpressionLike
|
||||
import com.cobblemon.mod.common.api.moves.MoveTemplate
|
||||
import com.cobblemon.mod.common.api.moves.TypeChart
|
||||
import com.cobblemon.mod.common.api.moves.adapters.MoveTemplateAdapter
|
||||
import com.cobblemon.mod.common.api.pokemon.effect.ShoulderEffect
|
||||
import com.cobblemon.mod.common.api.pokemon.effect.adapter.ShoulderEffectAdapter
|
||||
@@ -125,6 +126,7 @@ object PokemonSpecies : JsonDataRegistry<Species> {
|
||||
it.indicateSpeciesInitialized()
|
||||
// Reload this with the mod
|
||||
CobblemonHeldItemManager.load()
|
||||
TypeChart.load()
|
||||
Cobblemon.LOGGER.info("Loaded {} Pokémon species", this.speciesByIdentifier.size)
|
||||
this.observable.emit(this)
|
||||
}
|
||||
|
||||
+38
-2
@@ -12,6 +12,8 @@ import com.cobblemon.mod.common.api.conditional.RegistryLikeCondition
|
||||
import com.cobblemon.mod.common.api.spawning.context.FishingSpawningContext
|
||||
import com.cobblemon.mod.common.util.itemRegistry
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.enchantment.EnchantmentHelper
|
||||
import net.minecraft.world.item.enchantment.Enchantments
|
||||
import net.minecraft.world.level.block.Block
|
||||
|
||||
/**
|
||||
@@ -33,9 +35,43 @@ class FishingSpawningCondition: SpawningCondition<FishingSpawningContext>() {
|
||||
return false
|
||||
} else if (neededNearbyBlocks != null && neededNearbyBlocks!!.none { cond -> ctx.nearbyBlockTypes.any { cond.fits(it, ctx.blockRegistry) } }) {
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
|
||||
if (minLureLevel != null) { // check for the lureLevel of the rod
|
||||
val pokerodStack = ctx.rodStack
|
||||
val lureLevel = EnchantmentHelper.getItemEnchantmentLevel(
|
||||
ctx.enchantmentRegistry.getHolder(Enchantments.LURE).get(),
|
||||
pokerodStack
|
||||
)
|
||||
if (lureLevel < minLureLevel!!) {
|
||||
return false
|
||||
} else if (maxLureLevel != null && lureLevel > maxLureLevel!!) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
if (bait != null) { // check for the bait on the bobber
|
||||
val pokerodBait = ctx.rodBait?.item
|
||||
if (pokerodBait != bait) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
if (rodType != null) { // check for the type of pokerod being used
|
||||
val pokerodItem = ctx.rodItem
|
||||
if (pokerodItem?.pokeRodId != rodType) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
/*if (ctx is FishingSpawningContext && (ctx as FishingSpawningContext).rodItem != null) { // check if the bait attracts certain EV yields
|
||||
val pokerodItem = (ctx as FishingSpawningContext).rodItem
|
||||
|
||||
// todo check if the EV yield of the berry matches the bait EV attract maybe?
|
||||
|
||||
if (// todo if bait EV yield != EV yield of pokemon consideration //Registries.ITEM.getId(pokerodItem?.bait?.item).path == )
|
||||
return false
|
||||
}*/
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
-27
@@ -116,24 +116,6 @@ abstract class SpawningCondition<T : SpawningContext> {
|
||||
}
|
||||
) {
|
||||
return false
|
||||
} else if (minLureLevel != null && ctx is FishingSpawningContext) { // check for the lureLevel of the rod
|
||||
val pokerodStack = (ctx as FishingSpawningContext).rodStack
|
||||
val lureLevel = EnchantmentHelper.getItemEnchantmentLevel(ctx.enchantmentRegistry.getHolder(Enchantments.LURE).get(), pokerodStack)
|
||||
if (lureLevel < minLureLevel!!) {
|
||||
return false
|
||||
} else if (maxLureLevel != null && lureLevel > maxLureLevel!!) {
|
||||
return false
|
||||
}
|
||||
} else if (bait != null && ctx is FishingSpawningContext) { // check for the bait on the bobber
|
||||
val pokerodBait = (ctx as FishingSpawningContext).rodBait?.item
|
||||
if (pokerodBait != bait) {
|
||||
return false
|
||||
}
|
||||
} else if (rodType != null && ctx is FishingSpawningContext) { // check for the type of pokerod being used
|
||||
val pokerodItem = (ctx as FishingSpawningContext).rodItem
|
||||
if (pokerodItem?.pokeRodId != rodType) {
|
||||
return false
|
||||
}
|
||||
} else if (isSlimeChunk != null && isSlimeChunk != false) {
|
||||
val isSlimeChunk = WorldgenRandom.seedSlimeChunk(ctx.position.x shr 4, ctx.position.z shr 4, ctx.world.seed, 987234911L).nextInt(10) == 0
|
||||
|
||||
@@ -152,15 +134,6 @@ abstract class SpawningCondition<T : SpawningContext> {
|
||||
return random.nextInt(10) == 0*/
|
||||
}
|
||||
|
||||
/*else if (ctx is FishingSpawningContext && (ctx as FishingSpawningContext).rodItem != null) { // check if the bait attracts certain EV yields
|
||||
val pokerodItem = (ctx as FishingSpawningContext).rodItem
|
||||
|
||||
// todo check if the EV yield of the berry matches the bait EV attract maybe?
|
||||
|
||||
if (// todo if bait EV yield != EV yield of pokemon consideration //Registries.ITEM.getId(pokerodItem?.bait?.item).path == )
|
||||
return false
|
||||
}*/
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
-1
@@ -16,7 +16,6 @@ import com.cobblemon.mod.common.entity.pokemon.PokemonEntity
|
||||
import com.cobblemon.mod.common.pokemon.feature.SeasonFeatureHandler
|
||||
import com.cobblemon.mod.common.util.weightedSelection
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.entity.player.Player
|
||||
|
||||
/**
|
||||
* A [SpawnAction] that will spawn a single [PokemonEntity].
|
||||
|
||||
@@ -269,7 +269,7 @@ open class PartyStore(override val uuid: UUID) : PokemonStore<PartyPosition>() {
|
||||
BattlePokemon.playerOwned(it)
|
||||
}.also { if (healPokemon) it.effectedPokemon.heal() }
|
||||
}.toMutableList()
|
||||
if(leadingPokemon != null) {
|
||||
if (leadingPokemon != null) {
|
||||
Collections.rotate(result, result.size - this.indexOfFirst { it.uuid == leadingPokemon })
|
||||
}
|
||||
return result
|
||||
|
||||
+23
-11
@@ -102,20 +102,32 @@ open class PlayerPartyStore(
|
||||
for (pokemon in this) {
|
||||
// Awake from fainted
|
||||
if (pokemon.isFainted()) {
|
||||
pokemon.faintedTimer -= 1
|
||||
if (pokemon.faintedTimer <= -1) {
|
||||
val php = ceil(pokemon.maxHealth * Cobblemon.config.faintAwakenHealthPercent)
|
||||
pokemon.currentHealth = php.toInt()
|
||||
player.sendSystemMessage(Component.translatable("cobblemon.party.faintRecover", pokemon.getDisplayName()))
|
||||
//Skip awaken logic check if config value is 0
|
||||
if (Cobblemon.config.faintAwakenHealthPercent > 0) {
|
||||
pokemon.faintedTimer -= 1
|
||||
if (pokemon.faintedTimer <= -1) {
|
||||
val php = ceil(pokemon.maxHealth * Cobblemon.config.faintAwakenHealthPercent)
|
||||
pokemon.currentHealth = php.toInt()
|
||||
player.sendSystemMessage(
|
||||
Component.translatable(
|
||||
"cobblemon.party.faintRecover",
|
||||
pokemon.getDisplayName()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Passive healing while less than full health
|
||||
else if (pokemon.currentHealth < pokemon.maxHealth) {
|
||||
pokemon.healTimer--
|
||||
if (pokemon.healTimer <= -1) {
|
||||
pokemon.healTimer = Cobblemon.config.healTimer
|
||||
val healAmount = 1.0.coerceAtLeast(pokemon.maxHealth.toDouble() * Cobblemon.config.healPercent)
|
||||
pokemon.currentHealth = pokemon.currentHealth + round(healAmount).toInt()
|
||||
//Skip passive healing logic check if config value is 0
|
||||
if (Cobblemon.config.healPercent > 0) {
|
||||
pokemon.healTimer--
|
||||
if (pokemon.healTimer <= -1) {
|
||||
pokemon.healTimer = Cobblemon.config.healTimer
|
||||
val healAmount =
|
||||
1.0.coerceAtLeast(pokemon.maxHealth.toDouble() * Cobblemon.config.healPercent)
|
||||
pokemon.currentHealth = pokemon.currentHealth + round(healAmount).toInt()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,4 +216,4 @@ open class PlayerPartyStore(
|
||||
super.set(position, pokemon)
|
||||
pokemon.getOwnerPlayer()?.let { CobblemonCriteria.PARTY_CHECK.trigger(it, this) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,6 +100,10 @@ object BattleBuilder {
|
||||
)
|
||||
}
|
||||
|
||||
if (actor.pokemonList.any { it.entity?.isBusy == true }) {
|
||||
errors.participantErrors[actor] += BattleStartError.targetIsBusy(player.displayName ?: player.name)
|
||||
}
|
||||
|
||||
if (BattleRegistry.getBattleByParticipatingPlayer(player) != null) {
|
||||
errors.participantErrors[actor] += BattleStartError.alreadyInBattle(player)
|
||||
}
|
||||
@@ -178,6 +182,10 @@ object BattleBuilder {
|
||||
)
|
||||
}
|
||||
|
||||
if (actor.pokemonList.any { it.entity?.isBusy == true }) {
|
||||
errors.participantErrors[actor] += BattleStartError.targetIsBusy(player.displayName ?: player.name)
|
||||
}
|
||||
|
||||
if (BattleRegistry.getBattleByParticipatingPlayer(player) != null) {
|
||||
errors.participantErrors[actor] += BattleStartError.alreadyInBattle(player)
|
||||
}
|
||||
@@ -248,7 +256,7 @@ object BattleBuilder {
|
||||
val wildActor = PokemonBattleActor(pokemonEntity.pokemon.uuid, BattlePokemon(pokemonEntity.pokemon), fleeDistance)
|
||||
val errors = ErroredBattleStart()
|
||||
|
||||
if(playerTeam.isNotEmpty() && playerTeam[0].health <= 0){
|
||||
if (playerTeam.isNotEmpty() && playerTeam[0].health <= 0){
|
||||
errors.participantErrors[playerActor] += BattleStartError.insufficientPokemon(
|
||||
actorEntity = player,
|
||||
requiredCount = battleFormat.battleType.slotsPerActor,
|
||||
@@ -264,6 +272,10 @@ object BattleBuilder {
|
||||
)
|
||||
}
|
||||
|
||||
if (playerActor.pokemonList.any { it.entity?.isBusy == true }) {
|
||||
errors.participantErrors[playerActor] += BattleStartError.targetIsBusy(player.displayName ?: player.name)
|
||||
}
|
||||
|
||||
if (BattleRegistry.getBattleByParticipatingPlayer(player) != null) {
|
||||
errors.participantErrors[playerActor] += BattleStartError.alreadyInBattle(playerActor)
|
||||
}
|
||||
@@ -348,6 +360,10 @@ object BattleBuilder {
|
||||
)
|
||||
}
|
||||
|
||||
if (playerActor.pokemonList.any { it.entity?.isBusy == true }) {
|
||||
errors.participantErrors[playerActor] += BattleStartError.targetIsBusy(player.displayName ?: player.name)
|
||||
}
|
||||
|
||||
playerActor.battleTheme = npcEntity.getBattleTheme()
|
||||
|
||||
return if (errors.isEmpty) {
|
||||
@@ -394,7 +410,7 @@ interface BattleStartError {
|
||||
fun alreadyInBattle(pokemonEntity: PokemonEntity) = AlreadyInBattleError(pokemonEntity.uuid, pokemonEntity.effectiveName())
|
||||
fun alreadyInBattle(actor: BattleActor) = AlreadyInBattleError(actor.uuid, actor.getName())
|
||||
fun noParty(npcEntity: NPCEntity) = NoPartyError(npcEntity)
|
||||
fun targetIsBusy(targetName: MutableComponent) = BusyError(targetName)
|
||||
fun targetIsBusy(targetName: Component) = BusyError(targetName)
|
||||
fun insufficientPokemon(
|
||||
actorEntity: Entity,
|
||||
requiredCount: Int,
|
||||
@@ -474,7 +490,7 @@ class AlreadyInBattleError(
|
||||
}
|
||||
}
|
||||
class BusyError(
|
||||
val targetName: MutableComponent
|
||||
val targetName: Component
|
||||
): BattleStartError {
|
||||
override fun getMessageFor(entity: Entity) = battleLang("errors.busy", targetName)
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.battles.runner
|
||||
import com.cobblemon.mod.common.api.battles.model.PokemonBattle
|
||||
import com.cobblemon.mod.common.battles.runner.graal.GraalShowdownService
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonObject
|
||||
import java.util.UUID
|
||||
|
||||
/**
|
||||
@@ -30,6 +31,7 @@ interface ShowdownService {
|
||||
fun getAbilityIds(): JsonArray
|
||||
fun getMoves(): JsonArray
|
||||
fun getItemIds(): JsonArray
|
||||
fun getTypeChart(): JsonObject
|
||||
fun registerSpecies()
|
||||
fun registerBagItems()
|
||||
fun indicateSpeciesInitialized() {}
|
||||
@@ -38,4 +40,4 @@ interface ShowdownService {
|
||||
companion object {
|
||||
val service: ShowdownService by lazy { GraalShowdownService() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+7
@@ -16,6 +16,7 @@ import com.cobblemon.mod.common.battles.ShowdownInterpreter
|
||||
import com.cobblemon.mod.common.battles.runner.ShowdownService
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonObject
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.net.URI
|
||||
@@ -152,6 +153,12 @@ class GraalShowdownService : ShowdownService {
|
||||
return gson.fromJson(arrayResult, JsonArray::class.java)
|
||||
}
|
||||
|
||||
override fun getTypeChart(): JsonObject {
|
||||
val getCobbledItemIdsFn = context.getBindings("js").getMember("getTypeChart")
|
||||
val arrayResult = getCobbledItemIdsFn.execute().asString()
|
||||
return gson.fromJson(arrayResult, JsonObject::class.java)
|
||||
}
|
||||
|
||||
override fun registerSpecies() {
|
||||
val receiveSpeciesDataFn = this.context.getBindings("js").getMember("receiveSpeciesData")
|
||||
val jsArray = this.context.eval("js", "new Array();")
|
||||
|
||||
+8
@@ -18,6 +18,7 @@ import com.cobblemon.mod.common.pokemon.FormData
|
||||
import com.cobblemon.mod.common.pokemon.Species
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonObject
|
||||
import java.io.BufferedReader
|
||||
import java.io.InputStreamReader
|
||||
import java.io.OutputStreamWriter
|
||||
@@ -123,6 +124,13 @@ class SocketShowdownService(val host: String = "localhost", val port: Int = 1846
|
||||
return gson.fromJson(response, JsonArray::class.java)
|
||||
}
|
||||
|
||||
override fun getTypeChart(): JsonObject {
|
||||
writer.write(">getTypeChart")
|
||||
writer.flush()
|
||||
val response = readMessage()
|
||||
return gson.fromJson(response, JsonObject::class.java)
|
||||
}
|
||||
|
||||
private fun sendSpeciesData(species: Species, form: FormData?) {
|
||||
writer.write(">receiveSpeciesData ${gson.toJson(PokemonSpecies.ShowdownSpecies(species, form))}\n")
|
||||
acknowledge()
|
||||
|
||||
@@ -157,7 +157,7 @@ class GildedChestBlock(settings: Properties, val type: Type = Type.RED) : BaseEn
|
||||
// The yaw based on the block's facing direction
|
||||
val yaw = facingToYaw[state.getValue(HorizontalDirectionalBlock.FACING)] ?: 0.0F
|
||||
|
||||
entity.entityData.set(PokemonEntity.SPAWN_DIRECTION, facingToYaw[state.getValue(HorizontalDirectionalBlock.FACING)])
|
||||
entity.entityData.set(PokemonEntity.SPAWN_DIRECTION, yaw)
|
||||
val offsetDir = state.getValue(HorizontalDirectionalBlock.FACING)
|
||||
val vec = pos.toVec3d().add(offsetDir.stepX * 0.1 + 0.5, 0.0, offsetDir.stepZ * 0.1 + 0.5)
|
||||
entity.moveTo(vec.x, vec.y, vec.z, yaw, entity.xRot)
|
||||
|
||||
@@ -125,6 +125,7 @@ object ClientMoLangFunctions {
|
||||
val maxPitch = params.getDoubleOrNull(3) ?: 70F
|
||||
val minPitch = params.getDoubleOrNull(4) ?: -45F
|
||||
val maxYaw = params.getDoubleOrNull(5) ?: 45F
|
||||
val minYaw = params.getDoubleOrNull(6) ?: -45F
|
||||
ObjectValue(
|
||||
SingleBoneLookAnimation(
|
||||
bone = model.getPart(boneName),
|
||||
@@ -132,7 +133,8 @@ object ClientMoLangFunctions {
|
||||
yawMultiplier = yawMultiplier.toFloat(),
|
||||
maxPitch = maxPitch.toFloat(),
|
||||
minPitch = minPitch.toFloat(),
|
||||
maxYaw = maxYaw.toFloat()
|
||||
maxYaw = maxYaw.toFloat(),
|
||||
minYaw = minYaw.toFloat()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.gui
|
||||
|
||||
import net.minecraft.client.gui.components.Renderable
|
||||
|
||||
interface CobblemonRenderable : Renderable
|
||||
@@ -18,7 +18,7 @@ import net.minecraft.network.chat.Component
|
||||
class ExitButton(
|
||||
pX: Int, pY: Int,
|
||||
onPress: OnPress
|
||||
): Button(pX, pY, WIDTH.toInt(), HEIGHT.toInt(), Component.literal("Exit"), onPress, DEFAULT_NARRATION) {
|
||||
): Button(pX, pY, WIDTH.toInt(), HEIGHT.toInt(), Component.literal("Exit"), onPress, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
private const val WIDTH = 26F
|
||||
|
||||
@@ -31,7 +31,7 @@ abstract class ScrollingWidget<T : ObjectSelectionList.Entry<T>>(
|
||||
height, // Height
|
||||
top, // Top
|
||||
slotHeight // Slot Height
|
||||
) {
|
||||
), CobblemonRenderable {
|
||||
override fun renderListBackground(guiGraphics: GuiGraphics) {}
|
||||
override fun renderSelection(context: GuiGraphics, y: Int, entryWidth: Int, entryHeight: Int, borderColor: Int, fillColor: Int) {}
|
||||
override fun renderDecorations(context: GuiGraphics, mouseX: Int, mouseY: Int) {}
|
||||
|
||||
@@ -13,6 +13,7 @@ import com.cobblemon.mod.common.battles.ShowdownActionResponse
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.battle.ClientBattleActor
|
||||
import com.cobblemon.mod.common.client.battle.SingleActionRequest
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.battle.subscreen.BattleActionSelection
|
||||
import com.cobblemon.mod.common.client.gui.battle.subscreen.BattleBackButton
|
||||
import com.cobblemon.mod.common.client.gui.battle.subscreen.BattleGeneralActionSelection
|
||||
@@ -29,7 +30,7 @@ import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.screens.Screen
|
||||
|
||||
class BattleGUI : Screen(battleLang("gui.title")) {
|
||||
class BattleGUI : Screen(battleLang("gui.title")), CobblemonRenderable {
|
||||
companion object {
|
||||
const val OPTION_VERTICAL_SPACING = 3
|
||||
const val OPTION_HORIZONTAL_SPACING = 3
|
||||
|
||||
+3
-2
@@ -9,18 +9,19 @@
|
||||
package com.cobblemon.mod.common.client.gui.battle.subscreen
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.mojang.blaze3d.vertex.PoseStack
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
|
||||
class BattleBackButton(val x: Float, val y: Float) {
|
||||
class BattleBackButton(val x: Float, val y: Float) : CobblemonRenderable {
|
||||
companion object {
|
||||
const val WIDTH = 58
|
||||
const val HEIGHT = 34
|
||||
const val SCALE = 0.5F
|
||||
}
|
||||
|
||||
fun render(context: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
|
||||
override fun render(context: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
|
||||
blitk(
|
||||
matrixStack = context.pose(),
|
||||
texture = cobblemonResource("textures/gui/battle/battle_back.png"),
|
||||
|
||||
+47
-7
@@ -11,12 +11,11 @@ package com.cobblemon.mod.common.client.gui.battle.subscreen
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.moves.Moves
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.api.text.gold
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.api.moves.TypeChart
|
||||
import com.cobblemon.mod.common.api.text.*
|
||||
import com.cobblemon.mod.common.battles.*
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.battle.ActiveClientBattlePokemon
|
||||
import com.cobblemon.mod.common.client.battle.SingleActionRequest
|
||||
import com.cobblemon.mod.common.client.gui.MoveCategoryIcon
|
||||
import com.cobblemon.mod.common.client.gui.TypeIcon
|
||||
@@ -24,12 +23,16 @@ import com.cobblemon.mod.common.client.gui.battle.BattleGUI
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.util.battleLang
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import com.cobblemon.mod.common.util.math.toRGB
|
||||
import com.google.common.collect.Lists
|
||||
import net.fabricmc.loader.impl.util.StringUtil
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.resources.sounds.SimpleSoundInstance
|
||||
import net.minecraft.client.sounds.SoundManager
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import net.minecraft.util.Mth.floor
|
||||
|
||||
class BattleMoveSelection(
|
||||
@@ -91,16 +94,16 @@ class BattleMoveSelection(
|
||||
open val response: MoveActionResponse get() = MoveActionResponse(move.id, targetPnx)
|
||||
open val selectable: Boolean get() = !move.disabled
|
||||
|
||||
val targetPnx: String? get() = targetList?.let { targets ->
|
||||
val target: Targetable? get() = targetList?.let { targets ->
|
||||
return@let when {
|
||||
targets.isEmpty() -> null
|
||||
targets.size == 1 -> targets[0].getPNX()
|
||||
targets.size == 1 -> targets[0]
|
||||
else -> null // TODO: multi-battles
|
||||
}
|
||||
}
|
||||
val targetPnx: String? get() = target?.getPNX()
|
||||
|
||||
fun render(context: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
|
||||
|
||||
val selectConditionOpacity = moveSelection.opacity * if (!selectable) 0.5F else 1F
|
||||
|
||||
blitk(
|
||||
@@ -173,6 +176,8 @@ class BattleMoveSelection(
|
||||
opacity = moveSelection.opacity,
|
||||
centered = true
|
||||
)
|
||||
|
||||
drawTooltip(context, mouseX, mouseY)
|
||||
}
|
||||
|
||||
fun isHovered(mouseX: Double, mouseY: Double) = mouseX >= x && mouseX <= x + MOVE_WIDTH && mouseY >= y && mouseY <= y + MOVE_HEIGHT
|
||||
@@ -182,6 +187,41 @@ class BattleMoveSelection(
|
||||
moveSelection.playDownSound(Minecraft.getInstance().soundManager)
|
||||
moveSelection.battleGUI.selectAction(moveSelection.request, response)
|
||||
}
|
||||
|
||||
private fun drawTooltip(context: GuiGraphics, mouseX: Int, mouseY: Int) {
|
||||
if (!isHovered(mouseX.toDouble(), mouseY.toDouble())) return
|
||||
|
||||
val textTooltip: MutableList<MutableComponent> = mutableListOf()
|
||||
for (descriptionLine in StringUtil.wrapLines(moveTemplate.description.string, 80).split("\n")) {
|
||||
textTooltip.add(Component.literal(descriptionLine).gray())
|
||||
}
|
||||
|
||||
textTooltip.add(Component.literal(""))
|
||||
|
||||
if (moveTemplate.power > 0) textTooltip.add(lang("ui.power").append(String.format(": %d", moveTemplate.power.toInt())))
|
||||
if (moveTemplate.accuracy > 0) textTooltip.add(lang("ui.accuracy").append(String.format(": %d%%", moveTemplate.accuracy.toInt())))
|
||||
|
||||
if (moveTemplate.power > 0 && moveTemplate.target != MoveTarget.self && target is ActiveClientBattlePokemon) {
|
||||
val species = (target as ActiveClientBattlePokemon).battlePokemon?.species
|
||||
if (species != null) {
|
||||
val moveEffectiveness: Double = TypeChart.getMoveEffectiveness(elementalType, listOf(species.primaryType, species.secondaryType))
|
||||
|
||||
textTooltip.add(when {
|
||||
moveEffectiveness == 0.0 -> lang("battle.ui.effectiveness.immunity", moveEffectiveness).gray()
|
||||
moveEffectiveness < 1.0 -> lang("battle.ui.effectiveness.resistance", moveEffectiveness).gray()
|
||||
moveEffectiveness > 1.0 -> lang("battle.ui.effectiveness.super_effective", moveEffectiveness).yellow()
|
||||
else -> lang("battle.ui.effectiveness.normal", moveEffectiveness).white()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
context.renderTooltip(
|
||||
Minecraft.getInstance().font,
|
||||
Lists.transform(textTooltip, Component::getVisualOrderText),
|
||||
mouseX,
|
||||
mouseY
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun renderWidget(context: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
|
||||
|
||||
+2
-1
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.client.gui.battle.widgets
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.battle.ClientBattleMessageQueue
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.Minecraft
|
||||
@@ -32,7 +33,7 @@ class BattleMessagePane(
|
||||
FRAME_HEIGHT, // height
|
||||
1, // top
|
||||
LINE_HEIGHT
|
||||
) {
|
||||
), CobblemonRenderable {
|
||||
var opacity = 1F
|
||||
private var scrolling = false
|
||||
|
||||
|
||||
+2
-1
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common.client.gui.battle.widgets
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.battle.BattleGUI
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
@@ -28,7 +29,7 @@ class BattleOptionTile(
|
||||
val resource: ResourceLocation,
|
||||
val text: MutableComponent,
|
||||
val onClick: () -> Unit
|
||||
) : Renderable, GuiEventListener, NarratableEntry {
|
||||
) : CobblemonRenderable, GuiEventListener, NarratableEntry {
|
||||
companion object {
|
||||
const val OPTION_WIDTH = 90
|
||||
const val OPTION_HEIGHT = 26
|
||||
|
||||
+2
-1
@@ -17,6 +17,7 @@ import com.cobblemon.mod.common.api.molang.MoLangFunctions.addFunctions
|
||||
import com.cobblemon.mod.common.api.molang.MoLangFunctions.setup
|
||||
import com.cobblemon.mod.common.api.net.NetworkPacket
|
||||
import com.cobblemon.mod.common.client.ClientMoLangFunctions.setupClient
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.dialogue.widgets.DialogueBox
|
||||
import com.cobblemon.mod.common.client.gui.dialogue.widgets.DialoguePortraitWidget
|
||||
import com.cobblemon.mod.common.client.gui.dialogue.widgets.DialogueNameWidget
|
||||
@@ -36,7 +37,7 @@ import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.screens.Screen
|
||||
|
||||
class DialogueScreen(var dialogueDTO: DialogueDTO) : Screen("gui.dialogue".asTranslated()) {
|
||||
class DialogueScreen(var dialogueDTO: DialogueDTO) : Screen("gui.dialogue".asTranslated()), CobblemonRenderable {
|
||||
val speakers = dialogueDTO.speakers?.mapNotNull { (key, value) ->
|
||||
val name = value.name
|
||||
when (val face = value.face) {
|
||||
|
||||
+2
-1
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.client.gui.dialogue.widgets
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
@@ -22,7 +23,7 @@ class DialogueNameWidget(
|
||||
val width: Int,
|
||||
val height: Int,
|
||||
val text: MutableComponent?
|
||||
) : Renderable, GuiEventListener {
|
||||
) : CobblemonRenderable, GuiEventListener {
|
||||
companion object {
|
||||
val nameResource = cobblemonResource("textures/gui/dialogue/dialogue_name.png")
|
||||
}
|
||||
|
||||
+2
-1
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.client.gui.dialogue.widgets
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.dialogue.DialogueScreen
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
@@ -22,7 +23,7 @@ class DialoguePortraitWidget(
|
||||
val y: Int,
|
||||
val width: Int,
|
||||
val height: Int
|
||||
) : Renderable, GuiEventListener {
|
||||
) : CobblemonRenderable, GuiEventListener {
|
||||
companion object {
|
||||
val DIALOGUE_ARROW_HEIGHT = 11
|
||||
val DIALOGUE_ARROW_WIDTH = 6
|
||||
|
||||
+2
-1
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.client.gui.dialogue.widgets
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.gui.drawCenteredText
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.dialogue.DialogueScreen
|
||||
import com.cobblemon.mod.common.net.messages.client.dialogue.dto.DialogueInputDTO
|
||||
import com.cobblemon.mod.common.net.messages.server.dialogue.InputToDialoguePacket
|
||||
@@ -36,7 +37,7 @@ class DialogueTextInputWidget(
|
||||
width,
|
||||
height,
|
||||
"gui_dialogue_text_input".text()
|
||||
) {
|
||||
), CobblemonRenderable {
|
||||
init {
|
||||
setMaxLength(maxLength)
|
||||
isFocused = true
|
||||
|
||||
+2
-1
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common.client.gui.dialogue.widgets
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.dialogue.DialogueScreen
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
@@ -22,7 +23,7 @@ class DialogueTimerWidget(
|
||||
val y: Int,
|
||||
val width: Int,
|
||||
val height: Int,
|
||||
) : Renderable, GuiEventListener {
|
||||
) : CobblemonRenderable, GuiEventListener {
|
||||
companion object {
|
||||
val timerResource = cobblemonResource("textures/gui/dialogue/dialogue_timer_bar.png")
|
||||
}
|
||||
|
||||
+2
-1
@@ -15,6 +15,7 @@ import com.cobblemon.mod.common.battles.BattleFormat
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.battle.ClientBattleChallenge
|
||||
import com.cobblemon.mod.common.client.battle.ClientTeamRequest
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.net.messages.client.PlayerInteractOptionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.*
|
||||
@@ -35,7 +36,7 @@ class BattleConfigureGUI(
|
||||
private val packet: PlayerInteractOptionsPacket,
|
||||
private val activeRequest: ClientBattleChallenge? = null,
|
||||
private val activeTeamRequest: ClientTeamRequest? = null
|
||||
) : Screen(lang("ui.challenge.challenge_title")) {
|
||||
) : Screen(lang("ui.challenge.challenge_title")), CobblemonRenderable {
|
||||
companion object {
|
||||
const val SIZE = 113
|
||||
private val backgroundResource = cobblemonResource("textures/gui/interact/request/battle_request.png")
|
||||
|
||||
+2
-1
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common.client.gui.interact.battleRequest
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.Button
|
||||
@@ -25,7 +26,7 @@ class BattleRequestNavigationButton(
|
||||
private val forwardIcon: ResourceLocation = forwardButtonResource,
|
||||
private val backwardIcon: ResourceLocation = backwardsButtonResource,
|
||||
onPress: OnPress
|
||||
): Button(pX.toInt(), pY.toInt(), (WIDTH * SCALE).toInt(), (clickHeight * SCALE).toInt(), Component.literal("Navigation"), onPress, DEFAULT_NARRATION) {
|
||||
): Button(pX.toInt(), pY.toInt(), (WIDTH * SCALE).toInt(), (clickHeight * SCALE).toInt(), Component.literal("Navigation"), onPress, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
const val HEIGHT = 16
|
||||
|
||||
+2
-1
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common.client.gui.interact.battleRequest
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.Button
|
||||
@@ -21,7 +22,7 @@ class BattleResponseButton(
|
||||
pX: Int, pY: Int,
|
||||
private val accept: Boolean,
|
||||
onPress: OnPress
|
||||
): Button(pX, pY, (WIDTH * SCALE).toInt(), (HEIGHT * SCALE).toInt(), Component.literal("Navigation"), onPress, DEFAULT_NARRATION) {
|
||||
): Button(pX, pY, (WIDTH * SCALE).toInt(), (HEIGHT * SCALE).toInt(), Component.literal("Navigation"), onPress, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
private const val WIDTH = 34F
|
||||
|
||||
+2
-1
@@ -12,6 +12,7 @@ import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
@@ -24,7 +25,7 @@ class BattleRequestButton(
|
||||
pX: Int, pY: Int,
|
||||
var text: MutableComponent,
|
||||
onPress: OnPress
|
||||
): Button(pX, pY, (WIDTH * SCALE).toInt(), (HEIGHT * SCALE).toInt(), text, onPress, DEFAULT_NARRATION) {
|
||||
): Button(pX, pY, (WIDTH * SCALE).toInt(), (HEIGHT * SCALE).toInt(), text, onPress, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
private const val WIDTH = 69F
|
||||
|
||||
+2
-1
@@ -12,6 +12,7 @@ import com.cobblemon.mod.common.CobblemonNetwork
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.callback.MoveSelectDTO
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.ExitButton
|
||||
import com.cobblemon.mod.common.net.messages.server.callback.move.MoveSelectCancelledPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.callback.move.MoveSelectedPacket
|
||||
@@ -35,7 +36,7 @@ class MoveSelectConfiguration(
|
||||
|
||||
class MoveSelectGUI(
|
||||
val config: MoveSelectConfiguration
|
||||
) : Screen(Component.translatable("cobblemon.ui.interact.moveselect")) {
|
||||
) : Screen(Component.translatable("cobblemon.ui.interact.moveselect")), CobblemonRenderable {
|
||||
companion object {
|
||||
const val WIDTH = 122
|
||||
const val HEIGHT = 133
|
||||
|
||||
+2
-1
@@ -16,6 +16,7 @@ import com.cobblemon.mod.common.api.text.gold
|
||||
import com.cobblemon.mod.common.api.text.red
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.MoveCategoryIcon
|
||||
import com.cobblemon.mod.common.client.gui.TypeIcon
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
@@ -35,7 +36,7 @@ class MoveSlotButton(
|
||||
val ppMax: Int,
|
||||
val enabled: Boolean = true,
|
||||
onPress: OnPress
|
||||
) : Button(x, y, WIDTH, HEIGHT, Component.literal("Move"), onPress, CreateNarration { "".text() }) {
|
||||
) : Button(x, y, WIDTH, HEIGHT, Component.literal("Move"), onPress, CreateNarration { "".text() }), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
private val moveResource = cobblemonResource("textures/gui/summary/summary_move.png")
|
||||
|
||||
+2
-1
@@ -14,6 +14,7 @@ import com.cobblemon.mod.common.api.callback.PartySelectPokemonDTO
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.ExitButton
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.net.messages.server.callback.party.PartyPokemonSelectedPacket
|
||||
@@ -37,7 +38,7 @@ class PartySelectConfiguration(
|
||||
)
|
||||
class PartySelectGUI(
|
||||
val config: PartySelectConfiguration
|
||||
) : Screen(Component.translatable("cobblemon.ui.interact.moveselect")) {
|
||||
) : Screen(Component.translatable("cobblemon.ui.interact.moveselect")), CobblemonRenderable {
|
||||
companion object {
|
||||
const val WIDTH = 163
|
||||
const val HEIGHT = 132
|
||||
|
||||
+2
-1
@@ -13,6 +13,7 @@ import com.cobblemon.mod.common.api.pokemon.PokemonProperties
|
||||
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.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.drawProfilePokemon
|
||||
import com.cobblemon.mod.common.client.gui.summary.widgets.PartySlotWidget
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
@@ -42,7 +43,7 @@ class PartySlotButton(
|
||||
val enabled: Boolean = true,
|
||||
val parent: PartySelectGUI,
|
||||
onPress: OnPress
|
||||
) : Button(x, y, WIDTH, HEIGHT, Component.literal("Pokemon"), onPress, CreateNarration { "".text() }) {
|
||||
) : Button(x, y, WIDTH, HEIGHT, Component.literal("Pokemon"), onPress, CreateNarration { "".text() }), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
private val slotResource = cobblemonResource("textures/gui/interact/party_select_slot.png")
|
||||
|
||||
+2
-1
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.client.gui.interact.wheel
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.Button
|
||||
@@ -29,7 +30,7 @@ class InteractWheelButton(
|
||||
private val colour: () -> Vector3f?,
|
||||
onPress: OnPress,
|
||||
private val canHover: (Double, Double) -> Boolean
|
||||
) : Button(x, y, BUTTON_SIZE, BUTTON_SIZE, Component.literal("Interact"), onPress, DEFAULT_NARRATION) {
|
||||
) : Button(x, y, BUTTON_SIZE, BUTTON_SIZE, Component.literal("Interact"), onPress, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
const val BUTTON_SIZE = 69
|
||||
|
||||
+2
-1
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.client.gui.interact.wheel
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.startselection.widgets.preview.ArrowButton
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.google.common.collect.Multimap
|
||||
@@ -20,7 +21,7 @@ import net.minecraft.client.gui.screens.Screen
|
||||
import net.minecraft.network.chat.Component
|
||||
import kotlin.math.max
|
||||
|
||||
class InteractWheelGUI(private val options: Multimap<Orientation, InteractWheelOption>, title: Component) : Screen(title) {
|
||||
class InteractWheelGUI(private val options: Multimap<Orientation, InteractWheelOption>, title: Component) : Screen(title), CobblemonRenderable {
|
||||
companion object {
|
||||
const val SIZE = 140
|
||||
const val OPTION_SIZE = 71
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* 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.npc
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.util.asTranslated
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.Button
|
||||
import net.minecraft.client.resources.sounds.SimpleSoundInstance
|
||||
import net.minecraft.client.sounds.SoundManager
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
|
||||
class NPCEditorButton(
|
||||
var buttonX: Float,
|
||||
var buttonY: Float,
|
||||
var label: MutableComponent,
|
||||
var cycleButtonState: Boolean? = null,
|
||||
var buttonWidth: Int = Minecraft.getInstance().font.width(label) + (BUTTON_PADDING * 2),
|
||||
val silent: Boolean = false,
|
||||
val alignRight: Boolean = false,
|
||||
val clickAction: OnPress
|
||||
): Button(if (alignRight) (buttonX - buttonWidth).toInt() else buttonX.toInt(), buttonY.toInt(), buttonWidth, HEIGHT, "".text(), clickAction, DEFAULT_NARRATION) {
|
||||
|
||||
companion object {
|
||||
val HEIGHT = 16
|
||||
val BORDER_WIDTH = 2
|
||||
val BUTTON_PADDING = 6
|
||||
val buttonResource = cobblemonResource("textures/gui/npc/button_base.png")
|
||||
val buttonBorderResource = cobblemonResource("textures/gui/npc/button_border.png")
|
||||
}
|
||||
|
||||
var isWidgetActive = false
|
||||
|
||||
override fun renderWidget(context: GuiGraphics, mouseX: Int, mouseY: Int, partialTicks: Float) {
|
||||
val matrices = context.pose()
|
||||
|
||||
// Left border
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = buttonBorderResource,
|
||||
x = x,
|
||||
y = y,
|
||||
width = BORDER_WIDTH,
|
||||
height = HEIGHT,
|
||||
vOffset = if (isMouseOver(mouseX.toDouble(), mouseY.toDouble()) || isWidgetActive) HEIGHT else 0,
|
||||
textureWidth = 3,
|
||||
textureHeight = HEIGHT * 2,
|
||||
)
|
||||
// Base
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = buttonResource,
|
||||
x = x + BORDER_WIDTH,
|
||||
y = y,
|
||||
width = buttonWidth - (BORDER_WIDTH * 2),
|
||||
height = HEIGHT,
|
||||
vOffset = if (isMouseOver(mouseX.toDouble(), mouseY.toDouble()) || isWidgetActive) HEIGHT else 0,
|
||||
textureHeight = HEIGHT * 2,
|
||||
)
|
||||
// Right border
|
||||
blitk(
|
||||
matrixStack = matrices,
|
||||
texture = buttonBorderResource,
|
||||
x = x + (buttonWidth - BORDER_WIDTH),
|
||||
y = y,
|
||||
width = BORDER_WIDTH,
|
||||
height = HEIGHT,
|
||||
uOffset = 1,
|
||||
vOffset = if (isMouseOver(mouseX.toDouble(), mouseY.toDouble()) || isWidgetActive) HEIGHT else 0,
|
||||
textureWidth = 3,
|
||||
textureHeight = HEIGHT * 2,
|
||||
)
|
||||
|
||||
var buttonLabel = if (cycleButtonState != null) "options.${if (cycleButtonState as Boolean) "on" else "off"}.composed".asTranslated(label) else label
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = buttonLabel,
|
||||
x = x + (buttonWidth / 2),
|
||||
y = y + 4,
|
||||
centered = true,
|
||||
shadow = true
|
||||
)
|
||||
}
|
||||
|
||||
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
||||
if (active && isMouseOver(mouseX, mouseY)) {
|
||||
super.mouseClicked(mouseX, mouseY, button)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun playDownSound(soundManager: SoundManager) {
|
||||
if (active && !this.silent) {
|
||||
soundManager.play(SimpleSoundInstance.forUI(CobblemonSounds.GUI_CLICK, 1.0F))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,25 +8,36 @@
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.npc
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.gui.drawText
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.npc.widgets.ConfigVariableList
|
||||
import com.cobblemon.mod.common.client.gui.npc.widgets.NPCRenderWidget
|
||||
import com.cobblemon.mod.common.client.gui.npc.widgets.NPCRenderWidget.Companion.HEIGHT
|
||||
import com.cobblemon.mod.common.client.gui.npc.widgets.NPCRenderWidget.Companion.WIDTH
|
||||
import com.cobblemon.mod.common.client.gui.npc.widgets.SimpleNPCTextInputWidget
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.client.render.drawScaledTextJustifiedRight
|
||||
import com.cobblemon.mod.common.net.messages.client.npc.dto.NPCConfigurationDTO
|
||||
import com.cobblemon.mod.common.net.messages.server.npc.SaveNPCPacket
|
||||
import com.cobblemon.mod.common.util.asTranslated
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.Button
|
||||
import net.minecraft.client.gui.screens.Screen
|
||||
import java.util.UUID
|
||||
|
||||
class NPCEditorScreen(
|
||||
val npcId: Int,
|
||||
val dto: NPCConfigurationDTO
|
||||
) : Screen("gui.npc_editor.title".asTranslated()) {
|
||||
) : Screen("gui.npc_editor.title".asTranslated()), CobblemonRenderable {
|
||||
companion object {
|
||||
const val BASE_WIDTH = 331
|
||||
const val BASE_HEIGHT = 161
|
||||
const val BASE_WIDTH = 360
|
||||
const val BASE_HEIGHT = 220
|
||||
|
||||
val baseResource = cobblemonResource("textures/gui/npc/base.png")
|
||||
}
|
||||
|
||||
val middleX: Int
|
||||
@@ -41,53 +52,73 @@ class NPCEditorScreen(
|
||||
|
||||
override fun init() {
|
||||
super.init()
|
||||
addRenderableOnly(NPCRenderWidget(leftX + 6, topY + 22, dto.npcClass, dto.aspects))
|
||||
addRenderableOnly(NPCRenderWidget(leftX + 12, topY + 35, dto.npcClass, dto.aspects))
|
||||
addRenderableWidget(SimpleNPCTextInputWidget(
|
||||
texture = cobblemonResource("textures/gui/npc/basic_text_input.png"),
|
||||
getter = { dto.npcName.string },
|
||||
setter = { dto.npcName = it.text() },
|
||||
x = leftX + 6,
|
||||
y = topY + 80,
|
||||
width = 130,
|
||||
height = 22
|
||||
posX = leftX + 12,
|
||||
posY = topY + 9,
|
||||
width = 192,
|
||||
height = 22,
|
||||
maxLength = 32
|
||||
))
|
||||
|
||||
addRenderableWidget(SimpleNPCTextInputWidget(
|
||||
texture = cobblemonResource("textures/gui/npc/aspects_text_input.png"),
|
||||
getter = { dto.aspects.joinToString() },
|
||||
setter = {
|
||||
dto.aspects.clear()
|
||||
dto.aspects.addAll(it.split(",").map { it.trim() })
|
||||
},
|
||||
x = leftX + 6,
|
||||
y = topY + 100,
|
||||
width = 130,
|
||||
posX = leftX + 12,
|
||||
posY = topY + 155,
|
||||
width = 116,
|
||||
height = 40,
|
||||
maxLength = 75,
|
||||
maxLength = 72,
|
||||
wrap = true
|
||||
))
|
||||
|
||||
addRenderableWidget(
|
||||
Button
|
||||
.builder("Save".text()) {
|
||||
SaveNPCPacket(npcId, dto).sendToServer()
|
||||
this.minecraft!!.setScreen(null)
|
||||
}
|
||||
.pos(leftX + BASE_WIDTH - 42, topY + BASE_HEIGHT - 8)
|
||||
.size(40, 16)
|
||||
.build()
|
||||
NPCEditorButton(
|
||||
buttonX = leftX + 348F,
|
||||
buttonY = topY + 201F,
|
||||
label = lang("ui.generic.save"),
|
||||
alignRight = true
|
||||
) {
|
||||
SaveNPCPacket(npcId, dto).sendToServer()
|
||||
this.minecraft!!.setScreen(null)
|
||||
}
|
||||
)
|
||||
|
||||
addRenderableWidget(ConfigVariableList(leftX + 200, topY + 30, this))
|
||||
addRenderableWidget(ConfigVariableList(leftX + 134, topY + 35, this))
|
||||
}
|
||||
|
||||
override fun renderBlurredBackground(delta: Float) {}
|
||||
|
||||
override fun renderMenuBackground(context: GuiGraphics) {}
|
||||
|
||||
override fun isPauseScreen() = false
|
||||
|
||||
override fun render(context: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
|
||||
// blitk(
|
||||
// matrixStack = context.pose(),
|
||||
// texture = baseResource,
|
||||
// x = leftX,
|
||||
// y = topY,
|
||||
// height = BASE_HEIGHT,
|
||||
// width = BASE_WIDTH
|
||||
// )
|
||||
blitk(
|
||||
matrixStack = context.pose(),
|
||||
texture = baseResource,
|
||||
x = leftX,
|
||||
y = topY,
|
||||
height = BASE_HEIGHT,
|
||||
width = BASE_WIDTH
|
||||
)
|
||||
|
||||
var extendedId = npcId.toString()
|
||||
while (extendedId.length < 12) extendedId = "0$extendedId"
|
||||
|
||||
drawScaledTextJustifiedRight(
|
||||
context = context,
|
||||
text = extendedId.text(),
|
||||
x = leftX + 348,
|
||||
y = topY + 9,
|
||||
shadow = true
|
||||
)
|
||||
|
||||
super.render(context, mouseX, mouseY, delta)
|
||||
}
|
||||
}
|
||||
+43
-55
@@ -8,16 +8,19 @@
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.npc.widgets
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.npc.NPCClasses
|
||||
import com.cobblemon.mod.common.api.npc.configuration.NPCConfigVariable
|
||||
import com.cobblemon.mod.common.api.npc.configuration.NPCConfigVariable.NPCVariableType
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.npc.NPCEditorButton
|
||||
import com.cobblemon.mod.common.client.gui.npc.NPCEditorScreen
|
||||
import com.cobblemon.mod.common.client.gui.npc.widgets.ConfigVariableList.ConfigVariable
|
||||
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.client.gui.components.ContainerObjectSelectionList
|
||||
import net.minecraft.client.gui.components.CycleButton
|
||||
import net.minecraft.client.gui.components.EditBox
|
||||
import net.minecraft.client.gui.components.Tooltip
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener
|
||||
@@ -25,7 +28,7 @@ import net.minecraft.client.gui.narration.NarratableEntry
|
||||
|
||||
class ConfigVariableList(
|
||||
val listX: Int,
|
||||
val listY: Int,
|
||||
var listY: Int,
|
||||
val parent: NPCEditorScreen
|
||||
) : ContainerObjectSelectionList<ConfigVariable>(
|
||||
Minecraft.getInstance(),
|
||||
@@ -33,13 +36,15 @@ class ConfigVariableList(
|
||||
HEIGHT, // height
|
||||
0, // top
|
||||
SLOT_HEIGHT + SLOT_SPACING
|
||||
) {
|
||||
), CobblemonRenderable {
|
||||
companion object {
|
||||
const val WIDTH = 200
|
||||
const val HEIGHT = 120
|
||||
const val SLOT_WIDTH = 160
|
||||
const val WIDTH = 211
|
||||
const val HEIGHT = 160
|
||||
const val SLOT_WIDTH = 196
|
||||
const val SLOT_HEIGHT = 33
|
||||
const val SLOT_SPACING = 0
|
||||
|
||||
val textInputBackground = cobblemonResource("textures/gui/npc/text_input_base.png")
|
||||
}
|
||||
|
||||
private var scrolling = false
|
||||
@@ -47,15 +52,16 @@ class ConfigVariableList(
|
||||
override fun getRowWidth() = SLOT_WIDTH
|
||||
|
||||
init {
|
||||
listY += 4
|
||||
this.x = listX
|
||||
this.y = listY
|
||||
correctSize()
|
||||
setRenderHeader(false, 0)
|
||||
val npcClass = NPCClasses.getByIdentifier(parent.dto.npcClass)
|
||||
if (npcClass != null) {
|
||||
npcClass.config.forEach { t ->
|
||||
val value = parent.dto.variables[t.variableName] ?: t.defaultValue
|
||||
addEntry(ConfigVariable(t, value, this))
|
||||
npcClass.config.forEach { variable ->
|
||||
val value = parent.dto.variables[variable.variableName] ?: variable.defaultValue
|
||||
addEntry(ConfigVariable(variable, value, this))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -65,20 +71,12 @@ class ConfigVariableList(
|
||||
public override fun addEntry(entry: ConfigVariable) = super.addEntry(entry)
|
||||
public override fun removeEntry(entry: ConfigVariable) = super.removeEntry(entry)
|
||||
|
||||
override fun renderListSeparators(guiGraphics: GuiGraphics) {}
|
||||
|
||||
override fun renderWidget(context: GuiGraphics, mouseX: Int, mouseY: Int, partialTicks: Float) {
|
||||
correctSize()
|
||||
|
||||
super.renderWidget(context, mouseX, mouseY, partialTicks)
|
||||
|
||||
// Scroll Overlay
|
||||
// blitk(
|
||||
// matrixStack = context.pose(),
|
||||
// texture = scrollOverlayResource,
|
||||
// x = listX,
|
||||
// y = listY - 13,
|
||||
// height = 131,
|
||||
// width = WIDTH
|
||||
// )
|
||||
}
|
||||
|
||||
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
||||
@@ -114,7 +112,6 @@ class ConfigVariableList(
|
||||
|
||||
private fun correctSize() {
|
||||
setRectangle(WIDTH, HEIGHT, listX, (listY - 4))
|
||||
// setX(listX)
|
||||
}
|
||||
|
||||
fun isHovered(mouseX: Double, mouseY: Double) = mouseX.toFloat() in (x.toFloat()..(x.toFloat() + WIDTH)) && mouseY.toFloat() in (y.toFloat()..(y.toFloat() + HEIGHT))
|
||||
@@ -130,11 +127,12 @@ class ConfigVariableList(
|
||||
val editBox = EditBox(
|
||||
client.font,
|
||||
parent.listX,
|
||||
parent.listY + 4,
|
||||
if (variable.type == NPCVariableType.NUMBER) SLOT_WIDTH - 100 else SLOT_WIDTH,
|
||||
parent.listY + 8,
|
||||
SLOT_WIDTH - 8,
|
||||
SLOT_HEIGHT - 8,
|
||||
variable.displayName,
|
||||
).also {
|
||||
it.isBordered = false
|
||||
it.tooltip = Tooltip.create(variable.description)
|
||||
it.height = SLOT_HEIGHT - 16
|
||||
it.setMaxLength(250)
|
||||
@@ -147,18 +145,23 @@ class ConfigVariableList(
|
||||
it.setFilter { value -> value.toDoubleOrNull() != null || value.isBlank() || value == "." || value == "-" }
|
||||
}
|
||||
}
|
||||
val cycleButton = CycleButton.onOffBuilder(booleanValue).create(variable.displayName) { _, value ->
|
||||
booleanValue = value
|
||||
parent.parent.dto.variables[variable.variableName] = if (value) "1" else "0"
|
||||
val toggleButton = NPCEditorButton(
|
||||
parent.listX.toFloat(),
|
||||
parent.listY + 6F,
|
||||
variable.displayName.copy(),
|
||||
booleanValue,
|
||||
SLOT_WIDTH
|
||||
) {
|
||||
booleanValue = !booleanValue
|
||||
parent.parent.dto.variables[variable.variableName] = if (booleanValue) "1" else "0"
|
||||
(it as NPCEditorButton).cycleButtonState = booleanValue
|
||||
}.also {
|
||||
it.height = SLOT_HEIGHT - 14
|
||||
it.width = SLOT_WIDTH - 8
|
||||
it.tooltip = Tooltip.create(variable.description)
|
||||
}
|
||||
|
||||
init {
|
||||
if (variable.type == NPCVariableType.BOOLEAN) {
|
||||
children.add(cycleButton)
|
||||
children.add(toggleButton) // children.add(cycleButton)
|
||||
} else {
|
||||
children.add(editBox)
|
||||
}
|
||||
@@ -188,42 +191,27 @@ class ConfigVariableList(
|
||||
) {
|
||||
val x = rowLeft - 4
|
||||
val y = rowTop
|
||||
val matrixStack = context.pose()
|
||||
// blitk(
|
||||
// matrixStack = matrixStack,
|
||||
// texture = slotResource,
|
||||
// x = x,
|
||||
// y = y,
|
||||
// height = SLOT_HEIGHT,
|
||||
// width = rowWidth,
|
||||
// vOffset = if (isHovered) SLOT_HEIGHT else 0,
|
||||
// textureHeight = SLOT_HEIGHT * 2
|
||||
// )
|
||||
|
||||
if (variable.type == NPCVariableType.BOOLEAN) {
|
||||
cycleButton.x = x
|
||||
cycleButton.y = y + 6
|
||||
cycleButton.render(context, mouseX, mouseY, partialTicks)
|
||||
toggleButton.x = x
|
||||
toggleButton.y = y + 9
|
||||
toggleButton.render(context, mouseX, mouseY, partialTicks)
|
||||
} else {
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = variable.displayName.visualOrderText,
|
||||
x = x,
|
||||
y = y + 4
|
||||
y = y + 4,
|
||||
shadow = true
|
||||
)
|
||||
editBox.x = x
|
||||
editBox.y = y + 14
|
||||
|
||||
blitk(matrixStack = context.pose(), texture = textInputBackground, x = x, y = y + 16, height = 12, width = 1)
|
||||
blitk(matrixStack = context.pose(), texture = textInputBackground, x = x + 1, y = y + 15, height = 14, width = SLOT_WIDTH - 2)
|
||||
blitk(matrixStack = context.pose(), texture = textInputBackground, x = x + SLOT_WIDTH - 1, y = y + 16, height = 12, width = 1)
|
||||
|
||||
editBox.x = x + 4
|
||||
editBox.y = y + 18
|
||||
editBox.render(context, mouseX, mouseY, partialTicks)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// override fun mouseClicked(mouseX: Double, mouseY: Double, delta: Int): Boolean {
|
||||
// if (moveButton.isHovered(mouseX, mouseY) && canUnpasture()) {
|
||||
// moveButton.onPress()
|
||||
// return true
|
||||
// }
|
||||
// return false
|
||||
// }
|
||||
}
|
||||
}
|
||||
+14
-16
@@ -8,11 +8,10 @@
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.npc.widgets
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.gui.drawProfile
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.FloatingState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.repository.NPCModelRepository
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.Renderable
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener
|
||||
@@ -23,41 +22,40 @@ class NPCRenderWidget(
|
||||
val y: Int,
|
||||
var identifier: ResourceLocation,
|
||||
val aspects: MutableSet<String>
|
||||
) : Renderable, GuiEventListener {
|
||||
) : CobblemonRenderable, GuiEventListener {
|
||||
val state = FloatingState().also {
|
||||
it.currentAspects = aspects
|
||||
}
|
||||
|
||||
companion object {
|
||||
val profileBackgroundResource = cobblemonResource("textures/gui/npc/profile_background.png")
|
||||
const val WIDTH = 66
|
||||
const val HEIGHT = 66
|
||||
const val WIDTH = 116
|
||||
const val HEIGHT = 112
|
||||
}
|
||||
|
||||
override fun isFocused() = false
|
||||
override fun setFocused(focused: Boolean) {}
|
||||
override fun render(context: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
|
||||
blitk(
|
||||
matrixStack = context.pose(),
|
||||
texture = profileBackgroundResource,
|
||||
x = x,
|
||||
y = y,
|
||||
width = WIDTH,
|
||||
height = HEIGHT
|
||||
)
|
||||
|
||||
context.enableScissor(
|
||||
x,
|
||||
y,
|
||||
x + WIDTH,
|
||||
y + HEIGHT
|
||||
)
|
||||
context.pose().pushPose()
|
||||
context.pose().translate(x + WIDTH / 2F, y + HEIGHT / 2F, 0F)
|
||||
// Decrease on Z-axis to prevent model from rendering above other components like tooltips
|
||||
context.pose().translate(x + (WIDTH / 2F), y + HEIGHT + (HEIGHT / 4F), -500F)
|
||||
|
||||
drawProfile(
|
||||
repository = NPCModelRepository,
|
||||
resourceIdentifier = identifier,
|
||||
matrixStack = context.pose(),
|
||||
partialTicks = delta,
|
||||
scale = 30F,
|
||||
scale = 120F,
|
||||
state = state
|
||||
)
|
||||
|
||||
context.pose().popPose()
|
||||
context.disableScissor()
|
||||
}
|
||||
}
|
||||
+99
-46
@@ -9,89 +9,142 @@
|
||||
package com.cobblemon.mod.common.client.gui.npc.widgets
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.gui.drawCenteredText
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import net.minecraft.Util
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.EditBox
|
||||
import net.minecraft.network.chat.MutableComponent
|
||||
import net.minecraft.network.chat.contents.PlainTextContents.LiteralContents
|
||||
import net.minecraft.client.gui.screens.Screen
|
||||
import net.minecraft.client.renderer.RenderType
|
||||
import net.minecraft.network.chat.Style
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import kotlin.math.floor
|
||||
|
||||
class SimpleNPCTextInputWidget(
|
||||
getter: () -> String,
|
||||
val texture: ResourceLocation,
|
||||
val texture: ResourceLocation? = null,
|
||||
private val setter: (String) -> Unit,
|
||||
x: Int,
|
||||
y: Int,
|
||||
posX: Int,
|
||||
posY: Int,
|
||||
width: Int,
|
||||
height: Int,
|
||||
maxLength: Int = 100,
|
||||
val shadow: Boolean = true,
|
||||
val wrap: Boolean = false
|
||||
) : EditBox(
|
||||
Minecraft.getInstance().font,
|
||||
x,
|
||||
y,
|
||||
posX + TEXT_PADDING,
|
||||
posY,
|
||||
width,
|
||||
height,
|
||||
"input".text()
|
||||
) {
|
||||
), CobblemonRenderable {
|
||||
companion object {
|
||||
const val TEXT_PADDING = 4
|
||||
}
|
||||
|
||||
var focusedTime: Long = 0
|
||||
|
||||
init {
|
||||
setMaxLength(maxLength)
|
||||
isFocused = true
|
||||
focusedTime = Util.getMillis()
|
||||
value = getter()
|
||||
this.setResponder { setter(it) }
|
||||
setResponder { setter(it) }
|
||||
setFocused(false)
|
||||
isBordered = false
|
||||
}
|
||||
|
||||
override fun setFocused(focused: Boolean) {
|
||||
if (focused) focusedTime = Util.getMillis()
|
||||
super.setFocused(focused)
|
||||
}
|
||||
|
||||
override fun mouseClicked(mouseX: Double, mouseY: Double, button: Int): Boolean {
|
||||
return if (mouseX.toInt() in x..(x + width) && mouseY.toInt() in y..(y + height)) {
|
||||
isFocused = true
|
||||
true
|
||||
} else {
|
||||
false
|
||||
val clickedState = super.mouseClicked(mouseX, mouseY, button)
|
||||
|
||||
if (wrap) {
|
||||
val splitLines = Minecraft.getInstance().font.splitter.splitLines(value, width - 8, Style.EMPTY)
|
||||
val clickedLineIndex = floor((mouseY - y)/11).toInt()
|
||||
|
||||
if (clickedLineIndex >= 0 && splitLines.size > clickedLineIndex) {
|
||||
val lineAtIndex = splitLines.get(clickedLineIndex)
|
||||
var lineSubstring = ""
|
||||
for (char in lineAtIndex.string) {
|
||||
lineSubstring += char
|
||||
val startToLineWidth = Minecraft.getInstance().font.width(lineSubstring.text())
|
||||
if ((mouseX - x) <= startToLineWidth) break
|
||||
}
|
||||
var unwrappedLine = ""
|
||||
splitLines.forEachIndexed { index, line ->
|
||||
if (index == clickedLineIndex) {
|
||||
unwrappedLine += lineSubstring
|
||||
} else if (index < clickedLineIndex) {
|
||||
unwrappedLine += line.string
|
||||
}
|
||||
}
|
||||
|
||||
this.moveCursorTo(maxOf(0, unwrappedLine.length - 1), Screen.hasShiftDown())
|
||||
}
|
||||
}
|
||||
|
||||
return clickedState
|
||||
}
|
||||
|
||||
override fun renderWidget(context: GuiGraphics, mouseX: Int, mouseY: Int, delta: Float) {
|
||||
if (cursorPosition != value.length) {
|
||||
moveCursorToEnd(false)
|
||||
if (texture != null) {
|
||||
blitk(
|
||||
matrixStack = context.pose(),
|
||||
x = x,
|
||||
y = y,
|
||||
width = width,
|
||||
height = height,
|
||||
texture = texture
|
||||
)
|
||||
}
|
||||
|
||||
blitk(
|
||||
matrixStack = context.pose(),
|
||||
x = x,
|
||||
y = y,
|
||||
width = width,
|
||||
height = height,
|
||||
texture = texture
|
||||
)
|
||||
|
||||
context.pose().pushPose()
|
||||
val scale = 0.8F
|
||||
context.pose().scale(scale, scale, 1F)
|
||||
if (wrap) {
|
||||
val wrappedLines = Minecraft.getInstance().font.split(MutableComponent.create(LiteralContents(value)), ((width - 8) / scale).toInt())
|
||||
val showCursor = isFocused && ((Util.getMillis() - this.focusedTime) / 300L % 2L == 0L)
|
||||
val input = (if (isFocused) "${value}${if ((cursorPosition == value.length) && showCursor) "_" else ""}" else value)
|
||||
|
||||
var cursorLine = ""
|
||||
var cursorLineIndex = -1
|
||||
var cursorLinePos = 0
|
||||
var accumlatedLength = 0
|
||||
val wrappedLines = Minecraft.getInstance().font.splitter.splitLines(input, width - (TEXT_PADDING * 2), Style.EMPTY)
|
||||
|
||||
for ((index, line) in wrappedLines.withIndex()) {
|
||||
context.drawString(
|
||||
Minecraft.getInstance().font,
|
||||
line,
|
||||
((x + 4) / scale).toInt(),
|
||||
((y + index * 10 + 5) / scale).toInt(),
|
||||
0xFFFFFF,
|
||||
false
|
||||
accumlatedLength += line.string.length
|
||||
if (cursorLineIndex < 0 && accumlatedLength > cursorPosition) {
|
||||
cursorLineIndex = index
|
||||
cursorLine = line.string
|
||||
cursorLinePos = if (cursorLineIndex > 0) cursorPosition - (accumlatedLength - line.string.length) else cursorPosition
|
||||
}
|
||||
drawScaledText(
|
||||
context = context,
|
||||
text = line.string.text(),
|
||||
x = x,
|
||||
y = y + index * 10 + 1,
|
||||
colour = 0xDDDDDD,
|
||||
shadow = true
|
||||
)
|
||||
}
|
||||
|
||||
if (showCursor && !value.isEmpty() && cursorPosition != value.length) {
|
||||
val startToCursorWidth = Minecraft.getInstance().font.width((cursorLine.substring(0, cursorLinePos).text()))
|
||||
context.fill(
|
||||
RenderType.guiTextHighlight(),
|
||||
x + startToCursorWidth - 1,
|
||||
y + cursorLineIndex * 10 + 1,
|
||||
x + startToCursorWidth,
|
||||
y + (cursorLineIndex * 10 + 1) + 9,
|
||||
-3092272
|
||||
)
|
||||
}
|
||||
} else {
|
||||
drawCenteredText(
|
||||
context = context,
|
||||
text = value.text(),
|
||||
x = (x + width / 2F) / scale,
|
||||
y = (y + height / 2 - 4) / scale,
|
||||
shadow = true,
|
||||
colour = 0xFFFFFF
|
||||
)
|
||||
super.renderWidget(context, mouseX, mouseY, delta)
|
||||
}
|
||||
context.pose().popPose()
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -13,6 +13,7 @@ import com.cobblemon.mod.common.api.gui.blitk
|
||||
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.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.drawProfilePokemon
|
||||
import com.cobblemon.mod.common.client.gui.pc.StorageSlot
|
||||
import com.cobblemon.mod.common.client.gui.summary.widgets.PartySlotWidget
|
||||
@@ -40,7 +41,7 @@ class PasturePokemonScrollList(
|
||||
HEIGHT, // height
|
||||
0, // top
|
||||
SLOT_HEIGHT + SLOT_SPACING
|
||||
) {
|
||||
), CobblemonRenderable {
|
||||
companion object {
|
||||
const val WIDTH = 70
|
||||
const val HEIGHT = 120
|
||||
|
||||
+2
-1
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.client.gui.pasture
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.Button
|
||||
@@ -18,7 +19,7 @@ import net.minecraft.network.chat.Component
|
||||
class PastureSlotIconButton(
|
||||
var xPos: Int, var yPos: Int,
|
||||
onPress: OnPress
|
||||
) : Button(xPos, yPos, (SIZE * SCALE).toInt(), (SIZE * SCALE).toInt(), Component.literal("Pasture Move"), onPress, DEFAULT_NARRATION) {
|
||||
) : Button(xPos, yPos, (SIZE * SCALE).toInt(), (SIZE * SCALE).toInt(), Component.literal("Pasture Move"), onPress, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
const val SIZE = 14
|
||||
|
||||
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.client.gui.pasture
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
@@ -22,7 +23,7 @@ import net.minecraft.network.chat.Component
|
||||
class RecallButton(
|
||||
x: Int, y: Int,
|
||||
onPress: OnPress
|
||||
) : Button(x, y, WIDTH, HEIGHT, Component.literal("Retrieve"), onPress, DEFAULT_NARRATION) {
|
||||
) : Button(x, y, WIDTH, HEIGHT, Component.literal("Retrieve"), onPress, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
private const val WIDTH = 70
|
||||
|
||||
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common.client.gui.pc
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.Button
|
||||
@@ -21,7 +22,7 @@ class NavigationButton(
|
||||
pX: Int, pY: Int,
|
||||
private val forward: Boolean,
|
||||
onPress: OnPress
|
||||
): Button(pX, pY, (WIDTH * SCALE).toInt(), (HEIGHT * SCALE).toInt(), Component.literal("Navigation"), onPress, DEFAULT_NARRATION) {
|
||||
): Button(pX, pY, (WIDTH * SCALE).toInt(), (HEIGHT * SCALE).toInt(), Component.literal("Navigation"), onPress, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
private const val WIDTH = 8F
|
||||
|
||||
@@ -13,6 +13,7 @@ import com.cobblemon.mod.common.api.gui.blitk
|
||||
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.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.ExitButton
|
||||
import com.cobblemon.mod.common.client.gui.TypeIcon
|
||||
import com.cobblemon.mod.common.client.gui.summary.Summary
|
||||
@@ -40,7 +41,7 @@ class PCGUI(
|
||||
val pc: ClientPC,
|
||||
val party: ClientParty,
|
||||
val configuration: PCGUIConfiguration
|
||||
) : Screen(Component.translatable("cobblemon.ui.pc.title")) {
|
||||
) : Screen(Component.translatable("cobblemon.ui.pc.title")), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
const val BASE_WIDTH = 349
|
||||
|
||||
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.client.gui.pc
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
@@ -23,7 +24,7 @@ class ReleaseButton(
|
||||
x: Int, y: Int,
|
||||
private val parent: StorageWidget,
|
||||
onPress: OnPress
|
||||
) : Button(x, y, WIDTH, HEIGHT, Component.literal("Release"), onPress, DEFAULT_NARRATION) {
|
||||
) : Button(x, y, WIDTH, HEIGHT, Component.literal("Release"), onPress, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
private const val WIDTH = 58
|
||||
|
||||
+2
-1
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.client.gui.pc
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
@@ -24,7 +25,7 @@ class ReleaseConfirmButton(
|
||||
private val parent: StorageWidget,
|
||||
private val subKey: String,
|
||||
onPress: OnPress
|
||||
) : Button(x, y, WIDTH, HEIGHT, Component.literal("ReleaseConfirm"), onPress, DEFAULT_NARRATION) {
|
||||
) : Button(x, y, WIDTH, HEIGHT, Component.literal("ReleaseConfirm"), onPress, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
private const val WIDTH = 30
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.client.gui.pc
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.drawProfilePokemon
|
||||
import com.cobblemon.mod.common.client.gui.pasture.PasturePCGUIConfiguration
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
@@ -31,7 +32,7 @@ open class StorageSlot(
|
||||
x: Int, y: Int,
|
||||
private val parent: StorageWidget,
|
||||
onPress: OnPress
|
||||
) : Button(x, y, SIZE, SIZE, Component.literal("StorageSlot"), onPress, DEFAULT_NARRATION) {
|
||||
) : Button(x, y, SIZE, SIZE, Component.literal("StorageSlot"), onPress, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
val state = FloatingState()
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -29,6 +29,7 @@ import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.ClientMoLangFunctions.setupClient
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.BASE_HEIGHT
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.BASE_WIDTH
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.HEADER_BAR_HEIGHT
|
||||
@@ -75,7 +76,7 @@ class PokedexGUI private constructor(
|
||||
val type: PokedexType,
|
||||
val initSpecies: ResourceLocation?,
|
||||
val blockPos: BlockPos?
|
||||
): Screen(Component.translatable("cobblemon.ui.pokedex.title")) {
|
||||
): Screen(Component.translatable("cobblemon.ui.pokedex.title")), CobblemonRenderable {
|
||||
companion object {
|
||||
private val screenBackground = cobblemonResource("textures/gui/pokedex/pokedex_screen.png")
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.client.gui.pokedex
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.Button
|
||||
import net.minecraft.client.gui.narration.NarrationElementOutput
|
||||
@@ -27,7 +28,7 @@ class ScaledButton(
|
||||
val scale: Float = 0.5F,
|
||||
val silent: Boolean = false,
|
||||
val clickAction: Button.OnPress
|
||||
): Button(buttonX.toInt(), buttonY.toInt(), buttonWidth.toInt(), buttonHeight.toInt(), "".text(), clickAction, DEFAULT_NARRATION) {
|
||||
): Button(buttonX.toInt(), buttonY.toInt(), buttonWidth.toInt(), buttonHeight.toInt(), "".text(), clickAction, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
|
||||
var isWidgetActive = false
|
||||
|
||||
|
||||
+2
-1
@@ -13,6 +13,7 @@ import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.api.text.font
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.HALF_OVERLAY_HEIGHT
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.HALF_OVERLAY_WIDTH
|
||||
import com.cobblemon.mod.common.client.gui.pokedex.PokedexGUIConstants.SCALE
|
||||
@@ -33,7 +34,7 @@ class SearchWidget(
|
||||
height: Int,
|
||||
text: Component = "Search".text(),
|
||||
val update: () -> (Unit)
|
||||
): EditBox(Minecraft.getInstance().font, posX.toInt(), posY.toInt(), width, height, text) {
|
||||
): EditBox(Minecraft.getInstance().font, posX.toInt(), posY.toInt(), width, height, text), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
private val backgroundOverlay = cobblemonResource("textures/gui/pokedex/pokedex_screen_search_overlay.png")
|
||||
|
||||
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.client.gui.pokenav
|
||||
import com.cobblemon.mod.common.Cobblemon
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.summary.Summary
|
||||
import com.cobblemon.mod.common.client.keybind.boundKey
|
||||
import com.cobblemon.mod.common.client.keybind.keybinds.PokeNavigatorBinding
|
||||
@@ -28,7 +29,7 @@ import net.minecraft.network.chat.MutableComponent
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
|
||||
class PokeNav : Screen(Component.translatable("cobblemon.ui.pokenav.title")) {
|
||||
class PokeNav : Screen(Component.translatable("cobblemon.ui.pokenav.title")), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
// Limiting
|
||||
|
||||
+2
-1
@@ -12,6 +12,7 @@ import com.cobblemon.mod.common.api.gui.ColourLibrary
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.util.asTranslated
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
@@ -31,7 +32,7 @@ open class PokeNavImageButton(
|
||||
private val text: MutableComponent,
|
||||
private val canClick: () -> Boolean = { true }
|
||||
// TODO: Make lang key per button
|
||||
): Button(pX, pY, pWidth, pHeight, "cobblemon.ui.pokenav.narrator.backbutton".asTranslated(), onPress, DEFAULT_NARRATION) {
|
||||
): Button(pX, pY, pWidth, pHeight, "cobblemon.ui.pokenav.narrator.backbutton".asTranslated(), onPress, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
|
||||
override fun renderWidget(context: GuiGraphics, pMouseX: Int, pMouseY: Int, pPartialTicks: Float) {
|
||||
// Render Button Image
|
||||
|
||||
+4
-2
@@ -17,6 +17,7 @@ import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.startselection.widgets.CategoryList
|
||||
import com.cobblemon.mod.common.client.gui.startselection.widgets.ExitButton
|
||||
import com.cobblemon.mod.common.client.gui.startselection.widgets.preview.ArrowButton
|
||||
@@ -47,7 +48,7 @@ import net.minecraft.network.chat.Component
|
||||
* @author Qu
|
||||
* @since 2022-06-18
|
||||
*/
|
||||
class StarterSelectionScreen(private val categories: List<RenderableStarterCategory>): Screen("cobblemon.ui.starter.title".asTranslated()) {
|
||||
class StarterSelectionScreen(private val categories: List<RenderableStarterCategory>): Screen("cobblemon.ui.starter.title".asTranslated()), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
// Size of UI at scale 1
|
||||
@@ -132,7 +133,8 @@ class StarterSelectionScreen(private val categories: List<RenderableStarterCateg
|
||||
pX = x + 85, pY = y + 50,
|
||||
pWidth = 102, pHeight = 100,
|
||||
pokemon = this,
|
||||
baseScale = 2.0f
|
||||
baseScale = 2.0f,
|
||||
playCryOnClick = true,
|
||||
)
|
||||
|
||||
typeWidget = typeWidget(this, x, y)
|
||||
|
||||
+2
-1
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common.client.gui.startselection.widgets
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.startselection.StarterSelectionScreen
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.config.starter.RenderableStarterCategory
|
||||
@@ -37,7 +38,7 @@ class CategoryList(
|
||||
paneHeight,
|
||||
topOffset,
|
||||
entryHeight
|
||||
) {
|
||||
), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
private const val CATEGORY_BUTTON_WIDTH = 51.5f
|
||||
|
||||
+2
-1
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.client.gui.startselection.widgets
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.util.asTranslated
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
@@ -20,7 +21,7 @@ class ExitButton(
|
||||
pWidth: Int, pHeight: Int,
|
||||
pXTexStart: Int, pYTexStart: Int, pYDiffText: Int,
|
||||
onPress: OnPress
|
||||
): Button(pX, pY, EXIT_BUTTON_WIDTH.toInt(), EXIT_BUTTON_HEIGHT.toInt(), "cobblemon.ui.starter.narrator.backbutton".asTranslated(), onPress, DEFAULT_NARRATION) {
|
||||
): Button(pX, pY, EXIT_BUTTON_WIDTH.toInt(), EXIT_BUTTON_HEIGHT.toInt(), "cobblemon.ui.starter.narrator.backbutton".asTranslated(), onPress, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
private const val EXIT_BUTTON_WIDTH = 15.95F
|
||||
|
||||
+2
-1
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.client.gui.startselection.widgets.preview
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.Button
|
||||
@@ -22,7 +23,7 @@ class ArrowButton(
|
||||
right: Boolean,
|
||||
private val texture: ResourceLocation = if (right) RIGHT_ARROW_BUTTON_RESOURCE else LEFT_ARROW_BUTTON_RESOURCE,
|
||||
onPress: OnPress
|
||||
) : Button(pX, pY, pWidth, pHeight, Component.empty(), onPress, DEFAULT_NARRATION) {
|
||||
) : Button(pX, pY, pWidth, pHeight, Component.empty(), onPress, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
private val RIGHT_ARROW_BUTTON_RESOURCE = cobblemonResource("textures/gui/starterselection/starterselection_arrow_right.png")
|
||||
|
||||
+2
-1
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.client.gui.startselection.widgets.preview
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.gui.ColourLibrary
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
@@ -25,7 +26,7 @@ class SelectionButton(
|
||||
pX: Int, pY: Int,
|
||||
pWidth: Int, pHeight: Int,
|
||||
onPress: OnPress
|
||||
): Button(pX, pY, pWidth, pHeight, Component.literal("SelectionButton"), onPress, DEFAULT_NARRATION) {
|
||||
): Button(pX, pY, pWidth, pHeight, Component.literal("SelectionButton"), onPress, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
private val buttonTexture = cobblemonResource("textures/gui/starterselection/starterselection_button.png")
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.api.text.text
|
||||
import com.cobblemon.mod.common.client.CobblemonClient
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.ExitButton
|
||||
import com.cobblemon.mod.common.client.gui.TypeIcon
|
||||
import com.cobblemon.mod.common.client.gui.summary.widgets.EvolutionSelectScreen
|
||||
@@ -63,7 +64,7 @@ import net.minecraft.sounds.SoundEvent
|
||||
* @param selection The index the [party] will have as the base [selectedPokemon].
|
||||
*/
|
||||
class Summary private constructor(party: Collection<Pokemon?>, private val editable: Boolean, private val selection: Int): Screen(
|
||||
Component.translatable("cobblemon.ui.summary.title")), Schedulable {
|
||||
Component.translatable("cobblemon.ui.summary.title")), Schedulable, CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
const val BASE_WIDTH = 331
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.Button
|
||||
@@ -38,7 +39,7 @@ class SummaryButton(
|
||||
private val boldText: Boolean = true,
|
||||
private val largeText: Boolean = true,
|
||||
private val textScale: Float = 1F
|
||||
): Button(buttonX.toInt(), buttonY.toInt(), buttonWidth.toInt(), buttonHeight.toInt(), text, clickAction, DEFAULT_NARRATION) {
|
||||
): Button(buttonX.toInt(), buttonY.toInt(), buttonWidth.toInt(), buttonHeight.toInt(), text, clickAction, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
const val TEXT_HEIGHT = 9
|
||||
|
||||
+12
-2
@@ -23,7 +23,8 @@ class ModelWidget(
|
||||
var pokemon: RenderablePokemon,
|
||||
val baseScale: Float = 2.7F,
|
||||
var rotationY: Float = 35F,
|
||||
var offsetY: Double = 0.0
|
||||
var offsetY: Double = 0.0,
|
||||
val playCryOnClick: Boolean = false,
|
||||
): SoundlessWidget(pX, pY, pWidth, pHeight, Component.literal("Summary - ModelWidget")) {
|
||||
|
||||
companion object {
|
||||
@@ -70,6 +71,15 @@ class ModelWidget(
|
||||
matrices.popPose()
|
||||
}
|
||||
|
||||
override fun onClick(pMouseX: Double, pMouseY: Double) {
|
||||
override fun mouseClicked(pMouseX: Double, pMouseY: Double, pButton: Int): Boolean {
|
||||
if (this.isHovered) playCry()
|
||||
return super.mouseClicked(pMouseX, pMouseY, pButton)
|
||||
}
|
||||
|
||||
private fun playCry() {
|
||||
if (playCryOnClick) {
|
||||
state.activeAnimations.clear()
|
||||
state.addFirstAnimation(setOf("cry"))
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.client.gui.summary.widgets
|
||||
import com.cobblemon.mod.common.CobblemonNetwork
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.net.messages.server.pokemon.update.SetNicknamePacket
|
||||
import com.cobblemon.mod.common.net.serverhandling.pokemon.update.SetNicknameHandler.MAX_NAME_LENGTH
|
||||
@@ -28,7 +29,7 @@ class NicknameEntryWidget(
|
||||
): EditBox(
|
||||
Minecraft.getInstance().font,
|
||||
x, y, width, height, text
|
||||
) {
|
||||
), CobblemonRenderable {
|
||||
|
||||
var pokemonName = ""
|
||||
|
||||
|
||||
+2
-1
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.client.gui.summary.widgets.common
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.Minecraft
|
||||
@@ -29,7 +30,7 @@ abstract class SummaryScrollList<T : ObjectSelectionList.Entry<T>>(
|
||||
HEIGHT, // height
|
||||
0, // top
|
||||
slotHeight
|
||||
) {
|
||||
), CobblemonRenderable {
|
||||
companion object {
|
||||
const val WIDTH = 108
|
||||
const val HEIGHT = 112
|
||||
|
||||
+2
-1
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.client.gui.summary.widgets.screens
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.text.bold
|
||||
import com.cobblemon.mod.common.client.CobblemonResources
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
@@ -24,7 +25,7 @@ class SummaryTab(
|
||||
val label: MutableComponent? = null,
|
||||
val icon: ResourceLocation? = null,
|
||||
onPress: OnPress
|
||||
): Button(pX, pY, 50, 13, label, onPress, DEFAULT_NARRATION) {
|
||||
): Button(pX, pY, 50, 13, label, onPress, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
private var isActive = false
|
||||
|
||||
override fun renderWidget(context: GuiGraphics, pMouseX: Int, pMouseY: Int, pPartialTicks: Float) {
|
||||
|
||||
+2
-1
@@ -8,6 +8,7 @@
|
||||
|
||||
package com.cobblemon.mod.common.client.gui.summary.widgets.screens.moves
|
||||
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import net.minecraft.client.Minecraft
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.ObjectSelectionList
|
||||
@@ -24,7 +25,7 @@ class MoveDescriptionScrollList(
|
||||
30, // height
|
||||
0, // top
|
||||
slotHeight
|
||||
) {
|
||||
), CobblemonRenderable {
|
||||
private var scrolling = false
|
||||
|
||||
init {
|
||||
|
||||
+2
-1
@@ -10,6 +10,7 @@ package com.cobblemon.mod.common.client.gui.summary.widgets.screens.moves
|
||||
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.Button
|
||||
@@ -21,7 +22,7 @@ class ReorderMoveButton(
|
||||
val pX: Int, val pY: Int,
|
||||
private val isUp: Boolean,
|
||||
onPress: OnPress
|
||||
): Button((pX - OFFSET_X).toInt(), (pY + (if (isUp) OFFSET_Y_UP else OFFSET_Y_DOWN)), (WIDTH * SCALE).toInt(), (HEIGHT * SCALE).toInt(), Component.empty(), onPress, DEFAULT_NARRATION) {
|
||||
): Button((pX - OFFSET_X).toInt(), (pY + (if (isUp) OFFSET_Y_UP else OFFSET_Y_DOWN)), (WIDTH * SCALE).toInt(), (HEIGHT * SCALE).toInt(), Component.empty(), onPress, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
private const val WIDTH = 8
|
||||
|
||||
+2
-1
@@ -11,6 +11,7 @@ package com.cobblemon.mod.common.client.gui.summary.widgets.screens.moves
|
||||
import com.cobblemon.mod.common.CobblemonSounds
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.api.moves.MoveTemplate
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.client.gui.components.Button
|
||||
@@ -28,7 +29,7 @@ class SwapMoveButton(
|
||||
var move: MoveTemplate?,
|
||||
var movesWidget: MovesWidget,
|
||||
onPress: OnPress
|
||||
): Button((pX + OFFSET_X).toInt(), (pY + OFFSET_Y).toInt(), (WIDTH * SCALE).toInt(), (HEIGHT * SCALE).toInt(), Component.empty(), onPress, DEFAULT_NARRATION) {
|
||||
): Button((pX + OFFSET_X).toInt(), (pY + OFFSET_Y).toInt(), (WIDTH * SCALE).toInt(), (HEIGHT * SCALE).toInt(), Component.empty(), onPress, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
|
||||
override fun mouseDragged(d: Double, e: Double, i: Int, f: Double, g: Double): Boolean {
|
||||
return false
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
package com.cobblemon.mod.common.client.gui.trade
|
||||
|
||||
import com.cobblemon.mod.common.api.gui.blitk
|
||||
import com.cobblemon.mod.common.client.gui.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.drawProfilePokemon
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.FloatingState
|
||||
@@ -31,7 +32,7 @@ open class PartySlot(
|
||||
private val parent: TradeGUI,
|
||||
private val isOpposing: Boolean = false,
|
||||
onPress: OnPress
|
||||
) : Button(x, y, SIZE, SIZE, Component.literal("PartySlot"), onPress, DEFAULT_NARRATION) {
|
||||
) : Button(x, y, SIZE, SIZE, Component.literal("PartySlot"), onPress, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
val state = FloatingState()
|
||||
companion object {
|
||||
const val SIZE = 25
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.cobblemon.mod.common.api.gui.blitk
|
||||
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.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.render.drawScaledText
|
||||
import com.cobblemon.mod.common.util.cobblemonResource
|
||||
import com.cobblemon.mod.common.util.lang
|
||||
@@ -24,7 +25,7 @@ class TradeButton(
|
||||
x: Int, y: Int,
|
||||
val parent: TradeGUI,
|
||||
onPress: OnPress
|
||||
) : Button(x, y, WIDTH, HEIGHT, Component.literal("Trade"), onPress, DEFAULT_NARRATION) {
|
||||
) : Button(x, y, WIDTH, HEIGHT, Component.literal("Trade"), onPress, DEFAULT_NARRATION), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
private const val WIDTH = 53
|
||||
|
||||
@@ -16,6 +16,7 @@ import com.cobblemon.mod.common.api.storage.party.PartyPosition
|
||||
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.CobblemonRenderable
|
||||
import com.cobblemon.mod.common.client.gui.ExitButton
|
||||
import com.cobblemon.mod.common.client.gui.TypeIcon
|
||||
import com.cobblemon.mod.common.client.gui.summary.Summary
|
||||
@@ -52,7 +53,7 @@ class TradeGUI(
|
||||
val traderName: MutableComponent,
|
||||
val traderParty: MutableList<TradeablePokemon?>,
|
||||
val party: MutableList<TradeablePokemon?>
|
||||
): Screen(lang("trade.gui.title")) {
|
||||
): Screen(lang("trade.gui.title")), CobblemonRenderable {
|
||||
|
||||
companion object {
|
||||
const val BASE_WIDTH = 293
|
||||
|
||||
+2
-1
@@ -20,6 +20,7 @@ import com.cobblemon.mod.common.net.messages.server.BattleChallengePacket
|
||||
import com.cobblemon.mod.common.net.messages.server.RequestPlayerInteractionsPacket
|
||||
import com.cobblemon.mod.common.net.messages.server.SendOutPokemonPacket
|
||||
import com.cobblemon.mod.common.pokemon.Pokemon
|
||||
import com.cobblemon.mod.common.util.isUsingPokedex
|
||||
import com.cobblemon.mod.common.util.traceFirstEntityCollision
|
||||
import com.mojang.blaze3d.platform.InputConstants
|
||||
import net.minecraft.client.Minecraft
|
||||
@@ -43,7 +44,7 @@ object PartySendBinding : CobblemonBlockingKeyBinding(
|
||||
secondsSinceActioned = 0F
|
||||
}
|
||||
|
||||
fun canAction() = canApplyChange
|
||||
fun canAction() = canApplyChange && Minecraft.getInstance().player?.isUsingPokedex() == false
|
||||
|
||||
override fun onTick() {
|
||||
if (secondsSinceActioned < 100) {
|
||||
|
||||
+13
-27
@@ -21,6 +21,7 @@ import com.google.gson.JsonDeserializationContext
|
||||
import com.google.gson.JsonDeserializer
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonObject
|
||||
import net.minecraft.world.entity.Entity
|
||||
import java.lang.reflect.Type
|
||||
|
||||
/**
|
||||
@@ -43,35 +44,20 @@ class PoseAdapter(
|
||||
val pose = JsonPose(model, obj)
|
||||
|
||||
val conditionsList = mutableListOf<(PosableState) -> Boolean>()
|
||||
val mustBeTouchingWater = json.get("isTouchingWater")?.asBoolean
|
||||
if (mustBeTouchingWater != null) {
|
||||
conditionsList.add { mustBeTouchingWater == it.getEntity()?.isInWater }
|
||||
|
||||
fun addCondition(jsonKey: String, condition: (Entity, Boolean) -> Boolean) {
|
||||
json.get(jsonKey)?.asBoolean?.let { expectedValue ->
|
||||
conditionsList.add { it.getEntity()?.let { entity -> condition(entity, expectedValue) } ?: true }
|
||||
}
|
||||
}
|
||||
|
||||
val mustBeTouchingWaterOrRain = json.get("isInWaterOrRain")?.asBoolean
|
||||
if (mustBeTouchingWaterOrRain != null) {
|
||||
conditionsList.add { mustBeTouchingWaterOrRain == it.getEntity()?.isInWaterOrRain }
|
||||
}
|
||||
val mustBeSubmergedInWater = json.get("isUnderWater")?.asBoolean
|
||||
if (mustBeSubmergedInWater != null) {
|
||||
conditionsList.add { mustBeSubmergedInWater == it.getEntity()?.isUnderWater }
|
||||
}
|
||||
val mustBeStandingOnRedSand = json.get("isStandingOnRedSand")?.asBoolean
|
||||
if (mustBeStandingOnRedSand != null) {
|
||||
conditionsList.add { mustBeStandingOnRedSand == it.getEntity()?.isStandingOnRedSand() }
|
||||
}
|
||||
val mustBeStandingOnSand = json.get("isStandingOnSand")?.asBoolean
|
||||
if (mustBeStandingOnSand != null) {
|
||||
conditionsList.add { mustBeStandingOnSand == it.getEntity()?.isStandingOnSand() }
|
||||
}
|
||||
val mustBeStandingOnSandOrRedSand = json.get("isStandingOnSandOrRedSand")?.asBoolean
|
||||
if (mustBeStandingOnSandOrRedSand != null) {
|
||||
conditionsList.add { mustBeStandingOnSandOrRedSand == it.getEntity()?.isStandingOnSandOrRedSand() }
|
||||
}
|
||||
val mustBeDusk = json.get("isDusk")?.asBoolean
|
||||
if (mustBeDusk != null) {
|
||||
conditionsList.add { mustBeDusk == it.getEntity()?.isDusk() }
|
||||
}
|
||||
addCondition("isTouchingWater") { entity, expectedValue -> entity.isInWater == expectedValue }
|
||||
addCondition("isInWaterOrRain") { entity, expectedValue -> entity.isInWaterOrRain == expectedValue }
|
||||
addCondition("isUnderWater") { entity, expectedValue -> entity.isUnderWater == expectedValue }
|
||||
addCondition("isStandingOnRedSand") { entity, expectedValue -> entity.isStandingOnRedSand() == expectedValue }
|
||||
addCondition("isStandingOnSand") { entity, expectedValue -> entity.isStandingOnSand() == expectedValue }
|
||||
addCondition("isStandingOnSandOrRedSand") { entity, expectedValue -> entity.isStandingOnSandOrRedSand() == expectedValue }
|
||||
addCondition("isDusk") { entity, expectedValue -> entity.isDusk() == expectedValue }
|
||||
|
||||
conditionsList.addAll(poseConditionReader(json))
|
||||
|
||||
|
||||
+5
-7
@@ -35,6 +35,11 @@ open class BedrockActiveAnimation(
|
||||
it.afterAction = action
|
||||
}
|
||||
|
||||
override fun start(state: PosableState) {
|
||||
super.start(state)
|
||||
startedSeconds = state.animationSeconds
|
||||
}
|
||||
|
||||
override fun run(
|
||||
context: RenderContext,
|
||||
model: PosableModel,
|
||||
@@ -46,10 +51,6 @@ open class BedrockActiveAnimation(
|
||||
headPitch: Float,
|
||||
intensity: Float
|
||||
): Boolean {
|
||||
if (startedSeconds == -1F) {
|
||||
startedSeconds = state.animationSeconds
|
||||
}
|
||||
|
||||
return animation.run(context, model, state, state.animationSeconds - startedSeconds, limbSwing, limbSwingAmount, ageInTicks, intensity).also {
|
||||
if (!it) {
|
||||
afterAction(context, state)
|
||||
@@ -58,9 +59,6 @@ open class BedrockActiveAnimation(
|
||||
}
|
||||
|
||||
override fun applyEffects(entity: Entity?, state: PosableState, previousSeconds: Float, newSeconds: Float) {
|
||||
if (startedSeconds == -1F) {
|
||||
startedSeconds = state.animationSeconds
|
||||
}
|
||||
val previousSecondsOffset = previousSeconds - startedSeconds
|
||||
val currentSecondsOffset = newSeconds - startedSeconds
|
||||
animation.applyEffects(entity, state, previousSecondsOffset, currentSecondsOffset)
|
||||
|
||||
-74
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen1
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.frame.HeadedFrame
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Pose
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.MOVING_POSES
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.STATIONARY_POSES
|
||||
import com.cobblemon.mod.common.entity.PoseType.Companion.UI_POSES
|
||||
import net.minecraft.client.model.geom.ModelPart
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
class RaichuAlolanModel(root: ModelPart) : PokemonPosableModel(root), HeadedFrame {
|
||||
override val rootPart = root.registerChildWithAllChildren("raichu_alolan")
|
||||
override val head = getPart("head")
|
||||
|
||||
override var portraitScale = 2.3F
|
||||
override var portraitTranslation = Vec3(-0.2, 0.6, 0.0)
|
||||
|
||||
override var profileScale = 0.65F
|
||||
override var profileTranslation = Vec3(0.0, 0.75, 0.0)
|
||||
|
||||
lateinit var sleep: Pose
|
||||
lateinit var standing: Pose
|
||||
lateinit var walk: Pose
|
||||
lateinit var battleidle: Pose
|
||||
|
||||
override val cryAnimation = CryProvider { bedrockStateful("raichu_alolan", "cry") }
|
||||
|
||||
override fun registerPoses() {
|
||||
val blink = quirk { bedrockStateful("raichu_alolan", "blink") }
|
||||
|
||||
standing = registerPose(
|
||||
poseName = "standing",
|
||||
poseTypes = STATIONARY_POSES + UI_POSES,
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
animations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("raichu_alolan", "ground_idle")
|
||||
)
|
||||
)
|
||||
|
||||
sleep = registerPose(
|
||||
poseType = PoseType.SLEEP,
|
||||
animations = arrayOf(bedrock("raichu_alolan", "sleep"))
|
||||
)
|
||||
|
||||
walk = registerPose(
|
||||
poseName = "walk",
|
||||
poseTypes = MOVING_POSES,
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
animations = arrayOf(
|
||||
singleBoneLook(),
|
||||
bedrock("raichu_alolan", "ground_walk")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
// override fun getFaintAnimation(
|
||||
// pokemonEntity: PokemonEntity,
|
||||
// state: PosableState<PokemonEntity>
|
||||
// ) = if (state.isPosedIn(standing, walk, battleidle, sleep)) bedrockStateful("raichu_alolan", "faint") else null
|
||||
}
|
||||
+1
-1
@@ -179,7 +179,7 @@ class HippowdonModel (root: ModelPart) : PokemonPosableModel(root), HeadedFrame
|
||||
battleidle = registerPose(
|
||||
poseName = "battleidle",
|
||||
poseTypes = PoseType.STATIONARY_POSES,
|
||||
condition = { it.isBattling && it.getEntity()?.isStandingOnSandOrRedSand() == true },
|
||||
condition = { it.isBattling && it.getEntity()?.isStandingOnSandOrRedSand() != true },
|
||||
quirks = arrayOf(blink),
|
||||
transformedParts = arrayOf(
|
||||
sand.createTransformation().withVisibility(visibility = false),
|
||||
|
||||
-77
@@ -1,77 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 Cobblemon Contributors
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
package com.cobblemon.mod.common.client.render.models.blockbench.pokemon.gen6
|
||||
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.PosableState
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.CryProvider
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pokemon.PokemonPosableModel
|
||||
import com.cobblemon.mod.common.client.render.models.blockbench.pose.Pose
|
||||
import com.cobblemon.mod.common.entity.PoseType
|
||||
import com.cobblemon.mod.common.util.isBattling
|
||||
import net.minecraft.client.model.geom.ModelPart
|
||||
import net.minecraft.world.phys.Vec3
|
||||
|
||||
class TrevenantModel (root: ModelPart) : PokemonPosableModel(root) {
|
||||
override val rootPart = root.registerChildWithAllChildren("trevenant")
|
||||
|
||||
override var portraitScale = 1.6F
|
||||
override var portraitTranslation = Vec3(-0.2, 1.8, 0.0)
|
||||
|
||||
override var profileScale = 0.45F
|
||||
override var profileTranslation = Vec3(0.0, 0.93, 0.0)
|
||||
|
||||
lateinit var standing: Pose
|
||||
lateinit var walk: Pose
|
||||
lateinit var sleep: Pose
|
||||
lateinit var battleidle: Pose
|
||||
|
||||
override val cryAnimation = CryProvider { bedrockStateful("trevenant", "cry") }
|
||||
|
||||
override fun registerPoses() {
|
||||
val blink = quirk { bedrockStateful("trevenant", "blink")}
|
||||
sleep = registerPose(
|
||||
poseType = PoseType.SLEEP,
|
||||
animations = arrayOf(bedrock("trevenant", "sleep"))
|
||||
)
|
||||
|
||||
standing = registerPose(
|
||||
poseName = "stand",
|
||||
poseTypes = PoseType.STATIONARY_POSES + PoseType.UI_POSES,
|
||||
condition = { !it.isBattling },
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
animations = arrayOf(
|
||||
bedrock("trevenant", "ground_idle")
|
||||
)
|
||||
)
|
||||
walk = registerPose(
|
||||
poseName = "walk",
|
||||
poseTypes = PoseType.MOVING_POSES,
|
||||
transformTicks = 5,
|
||||
quirks = arrayOf(blink),
|
||||
animations = arrayOf(
|
||||
bedrock("trevenant", "ground_walk")
|
||||
)
|
||||
)
|
||||
battleidle = registerPose(
|
||||
poseName = "battle_idle",
|
||||
poseTypes = PoseType.STATIONARY_POSES,
|
||||
transformTicks = 10,
|
||||
quirks = arrayOf(blink),
|
||||
condition = { it.isBattling },
|
||||
animations = arrayOf(
|
||||
bedrock("trevenant", "battle_idle")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override fun getFaintAnimation(state: PosableState) = if (state.isPosedIn(standing, walk, sleep)) bedrockStateful("trevenant", "faint") else
|
||||
if (state.isPosedIn(battleidle)) bedrockStateful("trevenant", "battle_faint")
|
||||
else null
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user