Compare commits

...

83 Commits

Author SHA1 Message Date
Auxilor
a27ebb1b5c libreforge-updater 2022-07-24 22:49:45 +01:00
Auxilor
afafd86eaf libreforge-updater 2022-07-24 21:51:44 +01:00
Auxilor
49a2713017 libreforge-updater 2022-07-23 17:43:45 +01:00
Auxilor
a4263e8397 libreforge-updater 2022-07-22 14:21:36 +01:00
Auxilor
17f3aa8862 Updated kotlin 2022-07-22 14:17:51 +01:00
Auxilor
c94024ea19 libreforge-updater 2022-07-21 20:15:00 +01:00
Auxilor
1daa52e1f4 Changed pet display 2022-07-21 16:39:47 +01:00
Auxilor
a06808f802 Updated to 1.11.2 2022-07-21 16:15:23 +01:00
Auxilor
91cf08f0ac Fixed pets obstructing the view when looking up 2022-07-21 16:15:17 +01:00
Auxilor
9a7ff1760c Updated to 1.11.1 2022-07-21 15:50:40 +01:00
Will FP
f2c3f569b7 Merge pull request #10 from Sedri05/master
Fixed Default Pets
2022-07-21 15:25:03 +01:00
Auxilor
508cb3e216 libreforge-updater 2022-07-20 00:11:07 +01:00
Auxilor
5f998f4bad libreforge-updater 2022-07-13 21:23:31 +01:00
Auxilor
e4b468b0da libreforge-updater 2022-07-12 14:59:32 +01:00
Auxilor
675d2b8508 libreforge-updater 2022-07-11 16:17:10 +01:00
Auxilor
edddd67f58 Updated to 1.9.1 2022-07-09 14:51:48 +01:00
Auxilor
ed676e50c7 Fixed armor stand persistence 2022-07-09 14:51:41 +01:00
Auxilor
b36551a179 Improved pet entities 2022-07-09 14:50:03 +01:00
Auxilor
053f22258a libreforge-updater 2022-07-09 12:11:28 +01:00
Auxilor
a3a0783ea2 libreforge-updater 2022-07-05 18:33:01 +01:00
Auxilor
c7f25f17cd libreforge-updater 2022-07-04 18:46:02 +01:00
Auxilor
a489aaa53a More fixes 2022-07-03 16:24:30 +01:00
Auxilor
9e9a68fc45 More fixes 2022-07-03 16:24:16 +01:00
Auxilor
53b24b9dbb Updated to 1.7.3 2022-07-03 16:20:50 +01:00
Auxilor
4977dc1012 Fixed pets.yml 2022-07-03 16:20:42 +01:00
Sedri05
0bb4aa6d51 Update pets.yml 2022-07-03 01:30:07 +02:00
Auxilor
5b1eda604d Added many new base pets! 2022-06-30 23:03:15 +01:00
Auxilor
10e9edc011 libreforge-updater 2022-06-30 22:55:14 +01:00
Auxilor
ec11e9c475 libreforge-updater 2022-06-30 22:35:09 +01:00
Auxilor
eebe7427bc Set version 2022-06-26 13:10:19 +01:00
Auxilor
d2fa50a08c libreforge-updater 2022-06-26 13:03:25 +01:00
Auxilor
9fb80c594a libreforge-updater 2022-06-25 22:23:38 +01:00
Auxilor
915778d63f libreforge-updater 2022-06-24 13:58:43 +01:00
Auxilor
44911d5f97 Updated to 1.6.2 2022-06-23 21:18:30 +01:00
Auxilor
11a79a5352 libreforge-updater 2022-06-22 22:25:33 +01:00
Auxilor
9473deda7c Updated to 1.6.2 2022-06-22 13:59:42 +01:00
Auxilor
44676515b2 Fixed craft permission 2022-06-22 13:59:33 +01:00
Auxilor
4e7317e69a Updated to 1.6.1 2022-06-22 12:51:00 +01:00
Auxilor
8ca8018ab2 Added filters to xp gain 2022-06-22 12:50:51 +01:00
Auxilor
78e033990b libreforge-updater 2022-06-22 12:43:42 +01:00
Auxilor
033ac785d6 Merge remote-tracking branch 'origin/master'
# Conflicts:
#	gradle.properties
2022-06-21 18:49:52 +01:00
Auxilor
6ddf34f7f6 Updated to 1.5.1 2022-06-21 18:49:41 +01:00
Auxilor
fb889b2936 Added discover-recipes 2022-06-21 18:49:34 +01:00
Auxilor
dcf89687e3 libreforge-updater 2022-06-21 08:29:46 +01:00
Auxilor
2835eeaa5d libreforge-updater 2022-06-20 21:38:10 +01:00
Auxilor
1647a5dfaf 1.4.0 2022-06-20 21:36:33 +01:00
Auxilor
3d260e82ae Fixed pet GUI 2022-06-20 21:36:24 +01:00
Auxilor
1fdbd064a9 Updated libreforge 2022-06-20 18:06:02 +01:00
Auxilor
94d1802b51 libreforge-updater 2022-06-20 14:17:43 +01:00
Auxilor
8604bf7b46 Updated to 1.3.1 2022-06-20 14:09:46 +01:00
Will FP
c21eecae11 Merge pull request #3 from Sedri05/master
Fixed default perm for pets menu
2022-06-20 14:06:02 +01:00
Sedri05
80950aecf3 Fixed default perm for pets menu 2022-06-19 13:18:47 +02:00
Auxilor
6ad33e98fc libreforge-updater 2022-06-19 12:18:45 +01:00
Auxilor
c60c64c6b3 Added ravager pet 2022-06-18 15:32:39 +01:00
Auxilor
9eb67d5204 Updated to 1.2.0 2022-06-18 14:55:56 +01:00
Auxilor
77f08961b8 Added conditions to xp gain methods 2022-06-18 14:55:46 +01:00
Auxilor
be4c70e0c5 Updated comments 2022-06-18 13:24:56 +01:00
Auxilor
614831687f Updated README 2022-06-18 13:22:36 +01:00
Auxilor
3ea5d8f4d3 Fixed rotation 2022-06-18 13:19:13 +01:00
Auxilor
2e472abc98 Fixed softdepends 2022-06-18 13:18:25 +01:00
Auxilor
927c1fbcae Improved ModelEngine support 2022-06-18 13:16:21 +01:00
Auxilor
7e6b5c4b80 Added ModelEngine support 2022-06-18 13:09:56 +01:00
Auxilor
616e0c012b libreforge-updater 2022-06-18 12:20:08 +01:00
Auxilor
226aaac8c1 Downgraded for updater 2022-06-18 12:18:37 +01:00
Auxilor
34026be77b Added /ecopets reset 2022-06-18 12:10:32 +01:00
Auxilor
8b585af4e2 Fixed /ecopets givexp 2022-06-18 12:06:51 +01:00
Auxilor
4cd7398d76 Improved /ecopets givexp 2022-06-18 11:59:00 +01:00
Auxilor
c84a2a10f6 Revert "Improved pet tick performance"
This reverts commit 6dcfd4ccaa.
2022-06-18 11:54:08 +01:00
Auxilor
6dcfd4ccaa Improved pet tick performance 2022-06-18 11:53:34 +01:00
Auxilor
428df89ed1 Improved PR 2022-06-18 11:44:11 +01:00
Will FP
ebe542ef2b Merge pull request #1
Added givexp command
2022-06-18 11:43:44 +01:00
Auxilor
d3d005845a Improved pages 2022-06-18 11:43:14 +01:00
Sedri05
5d4eedfef6 added msg on invalid player 2022-06-18 12:33:18 +02:00
Sedri05
c362ad0d18 It can now run in console 2022-06-18 12:32:10 +02:00
Sedri05
2d56e8a9d7 Added givexp command 2022-06-18 12:28:33 +02:00
Auxilor
56c7268bb9 Fixed config 2022-06-18 11:20:31 +01:00
Auxilor
447c2c877a Updated config 2022-06-18 11:20:08 +01:00
Auxilor
1c0c9ba259 Added pages to pet GUI 2022-06-18 11:19:36 +01:00
Auxilor
6f5a8b9df2 Updated to 1.1.0 2022-06-18 10:55:02 +01:00
Auxilor
cbbe5b590e Added getActivePet to API 2022-06-18 10:54:54 +01:00
Auxilor
fa3c5b8020 Added polymart resource ID 2022-06-18 10:49:07 +01:00
Auxilor
7a34a2d38c Added skeleton pet 2022-06-18 10:47:54 +01:00
Auxilor
0f14f36b2f Fixed missing placeholder 2022-06-18 00:34:33 +01:00
25 changed files with 1236 additions and 84 deletions

View File

@@ -21,7 +21,7 @@
</a> </a>
</p> </p>
[![Docs](https://i.imgur.com/6GFV1bQ.png)](https://discord.gg/ZcwpSsE/) [![Docs](https://i.imgur.com/4JciYrQ.png)](https://discord.gg/ZcwpSsE/)
## License ## License
*Click here to read [the entire license](https://github.com/Auxilor/EcoPets/blob/master/LICENSE.md).* *Click here to read [the entire license](https://github.com/Auxilor/EcoPets/blob/master/LICENSE.md).*

View File

@@ -4,7 +4,7 @@ buildscript {
} }
dependencies { dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.21" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.10"
} }
} }
@@ -34,6 +34,7 @@ allprojects {
maven { url 'https://repo.codemc.io/repository/maven-public/' } maven { url 'https://repo.codemc.io/repository/maven-public/' }
maven { url 'https://repo.dmulloy2.net/repository/public/' } maven { url 'https://repo.dmulloy2.net/repository/public/' }
maven { url 'https://repo.essentialsx.net/releases/' } maven { url 'https://repo.essentialsx.net/releases/' }
maven { url 'https://mvn.lumine.io/repository/maven-public/' }
} }
jar { jar {
@@ -47,12 +48,12 @@ allprojects {
dependencies { dependencies {
compileOnly 'com.willfp:eco:6.37.1' compileOnly 'com.willfp:eco:6.37.1'
implementation 'com.willfp:libreforge:3.63.0' implementation 'com.willfp:libreforge:3.77.0'
implementation 'org.joml:joml:1.10.4' implementation 'org.joml:joml:1.10.4'
compileOnly 'org.jetbrains:annotations:23.0.0' compileOnly 'org.jetbrains:annotations:23.0.0'
compileOnly 'org.jetbrains.kotlin:kotlin-stdlib:1.6.21' compileOnly 'org.jetbrains.kotlin:kotlin-stdlib:1.7.10'
} }
tasks.withType(JavaCompile) { tasks.withType(JavaCompile) {

View File

@@ -7,6 +7,7 @@ dependencies {
compileOnly 'net.kyori:adventure-api:4.10.1' compileOnly 'net.kyori:adventure-api:4.10.1'
compileOnly 'net.essentialsx:EssentialsX:2.19.0' compileOnly 'net.essentialsx:EssentialsX:2.19.0'
compileOnly 'com.github.ben-manes.caffeine:caffeine:3.0.6' compileOnly 'com.github.ben-manes.caffeine:caffeine:3.0.6'
compileOnly 'com.ticxo.modelengine:api:R2.5.0'
} }
build.dependsOn publishToMavenLocal build.dependsOn publishToMavenLocal

View File

@@ -2,6 +2,7 @@ package com.willfp.ecopets
import com.willfp.ecopets.api.EcoPetsAPI import com.willfp.ecopets.api.EcoPetsAPI
import com.willfp.ecopets.pets.Pet import com.willfp.ecopets.pets.Pet
import com.willfp.ecopets.pets.activePet
import com.willfp.ecopets.pets.getPetLevel import com.willfp.ecopets.pets.getPetLevel
import com.willfp.ecopets.pets.getPetProgress import com.willfp.ecopets.pets.getPetProgress
import com.willfp.ecopets.pets.getPetXP import com.willfp.ecopets.pets.getPetXP
@@ -14,6 +15,8 @@ import org.bukkit.entity.Player
internal object EcoPetsAPIImpl : EcoPetsAPI { internal object EcoPetsAPIImpl : EcoPetsAPI {
override fun hasPet(player: OfflinePlayer, pet: Pet) = player.hasPet(pet) override fun hasPet(player: OfflinePlayer, pet: Pet) = player.hasPet(pet)
override fun getActivePet(player: OfflinePlayer): Pet? = player.activePet
override fun getPetLevel(player: OfflinePlayer, pet: Pet) = player.getPetLevel(pet) override fun getPetLevel(player: OfflinePlayer, pet: Pet) = player.getPetLevel(pet)
override fun givePetExperience(player: Player, pet: Pet, amount: Double) = override fun givePetExperience(player: Player, pet: Pet, amount: Double) =

View File

@@ -1,17 +1,21 @@
package com.willfp.ecopets package com.willfp.ecopets
import com.willfp.eco.core.command.impl.PluginCommand import com.willfp.eco.core.command.impl.PluginCommand
import com.willfp.eco.core.integrations.IntegrationLoader
import com.willfp.eco.core.placeholder.PlayerPlaceholder import com.willfp.eco.core.placeholder.PlayerPlaceholder
import com.willfp.eco.util.toSingletonList import com.willfp.eco.util.toSingletonList
import com.willfp.ecopets.commands.CommandEcopets import com.willfp.ecopets.commands.CommandEcopets
import com.willfp.ecopets.commands.CommandPets import com.willfp.ecopets.commands.CommandPets
import com.willfp.ecopets.config.PetsYml import com.willfp.ecopets.config.PetsYml
import com.willfp.ecopets.pets.DiscoverRecipeListener
import com.willfp.ecopets.pets.PetDisplay import com.willfp.ecopets.pets.PetDisplay
import com.willfp.ecopets.pets.PetLevelListener import com.willfp.ecopets.pets.PetLevelListener
import com.willfp.ecopets.pets.PetTriggerXPGainListener import com.willfp.ecopets.pets.PetTriggerXPGainListener
import com.willfp.ecopets.pets.SpawnEggHandler import com.willfp.ecopets.pets.SpawnEggHandler
import com.willfp.ecopets.pets.activePet import com.willfp.ecopets.pets.activePet
import com.willfp.ecopets.pets.activePetLevel import com.willfp.ecopets.pets.activePetLevel
import com.willfp.ecopets.pets.entity.ModelEnginePetEntity
import com.willfp.ecopets.pets.entity.PetEntity
import com.willfp.libreforge.LibReforgePlugin import com.willfp.libreforge.LibReforgePlugin
import org.bukkit.event.Listener import org.bukkit.event.Listener
@@ -48,6 +52,16 @@ class EcoPetsPlugin : LibReforgePlugin() {
petDisplay.shutdown() petDisplay.shutdown()
} }
override fun loadAdditionalIntegrations(): List<IntegrationLoader> {
return listOf(
IntegrationLoader("ModelEngine") {
PetEntity.registerPetEntity("modelengine") { pet, id ->
ModelEnginePetEntity(pet, id)
}
}
)
}
override fun loadPluginCommands(): List<PluginCommand> { override fun loadPluginCommands(): List<PluginCommand> {
return listOf( return listOf(
CommandEcopets(this), CommandEcopets(this),
@@ -60,7 +74,8 @@ class EcoPetsPlugin : LibReforgePlugin() {
PetLevelListener(this), PetLevelListener(this),
PetTriggerXPGainListener, PetTriggerXPGainListener,
SpawnEggHandler(this), SpawnEggHandler(this),
petDisplay petDisplay,
DiscoverRecipeListener(this)
) )
} }

View File

@@ -18,6 +18,16 @@ interface EcoPetsAPI {
pet: Pet pet: Pet
): Boolean ): Boolean
/**
* Get a player's active pet.
*
* @param player The player.
* @return The active pet.
*/
fun getActivePet(
player: OfflinePlayer
): Pet?
/** /**
* Get a player's level of a certain pet. * Get a player's level of a certain pet.
* *

View File

@@ -9,6 +9,8 @@ class CommandEcopets(plugin: EcoPlugin) : PluginCommand(plugin, "ecopets", "ecop
this.addSubcommand(CommandReload(plugin)) this.addSubcommand(CommandReload(plugin))
.addSubcommand(CommandGive(plugin)) .addSubcommand(CommandGive(plugin))
.addSubcommand(CommandGiveEgg(plugin)) .addSubcommand(CommandGiveEgg(plugin))
.addSubcommand(CommandGiveXP(plugin))
.addSubcommand(CommandReset(plugin))
} }
override fun onExecute(sender: CommandSender, args: List<String>) { override fun onExecute(sender: CommandSender, args: List<String>) {

View File

@@ -0,0 +1,89 @@
package com.willfp.ecopets.commands
import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.core.command.impl.Subcommand
import com.willfp.eco.util.StringUtils
import com.willfp.eco.util.savedDisplayName
import com.willfp.eco.util.toNiceString
import com.willfp.ecopets.pets.Pets
import com.willfp.ecopets.pets.givePetExperience
import com.willfp.ecopets.pets.hasPet
import org.bukkit.Bukkit
import org.bukkit.command.CommandSender
import org.bukkit.entity.Player
import org.bukkit.util.StringUtil
class CommandGiveXP(plugin: EcoPlugin) : Subcommand(plugin, "givexp", "ecopets.command.givexp", false) {
override fun onExecute(sender: CommandSender, args: List<String>) {
if (args.isEmpty()) {
sender.sendMessage(plugin.langYml.getMessage("needs-player"))
return
}
if (args.size == 1) {
sender.sendMessage(plugin.langYml.getMessage("needs-pet"))
return
}
if (args.size == 2) {
sender.sendMessage(plugin.langYml.getMessage("needs-amount"))
return
}
val playerName = args[0]
val player = Bukkit.getPlayer(playerName)
if (player == null) {
sender.sendMessage(plugin.langYml.getMessage("invalid-player"))
return
}
val pet = Pets.getByID(args[1])
if (pet == null) {
sender.sendMessage(plugin.langYml.getMessage("invalid-pet"))
return
}
if (!player.hasPet(pet)) {
sender.sendMessage(plugin.langYml.getMessage("doesnt-have-pet"))
return
}
val amount = args[2].toDoubleOrNull()
if (amount == null) {
sender.sendMessage(plugin.langYml.getMessage("invalid-amount"))
return
}
player.givePetExperience(
pet,
amount
)
sender.sendMessage(
plugin.langYml.getMessage("gave-xp", StringUtils.FormatOption.WITHOUT_PLACEHOLDERS)
.replace("%player%", player.savedDisplayName)
.replace("%xp%", amount.toNiceString())
.replace("%pet%", pet.name)
)
}
override fun tabComplete(sender: CommandSender, args: List<String>): List<String> {
if (args.size == 1) {
return Bukkit.getOnlinePlayers().map { it.name }
}
if (args.size == 2) {
return Pets.values().map { it.id }
}
if (args.size == 3) {
return listOf("10", "100", "1000", "10000")
}
return emptyList()
}
}

View File

@@ -0,0 +1,76 @@
package com.willfp.ecopets.commands
import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.core.command.impl.Subcommand
import com.willfp.eco.util.StringUtils
import com.willfp.eco.util.savedDisplayName
import com.willfp.eco.util.toNiceString
import com.willfp.ecopets.pets.Pets
import com.willfp.ecopets.pets.activePet
import com.willfp.ecopets.pets.givePetExperience
import com.willfp.ecopets.pets.hasPet
import com.willfp.ecopets.pets.setPetLevel
import com.willfp.ecopets.pets.setPetXP
import org.bukkit.Bukkit
import org.bukkit.command.CommandSender
import org.bukkit.entity.Player
import org.bukkit.util.StringUtil
class CommandReset(plugin: EcoPlugin) : Subcommand(plugin, "reset", "ecopets.command.reset", false) {
override fun onExecute(sender: CommandSender, args: List<String>) {
if (args.isEmpty()) {
sender.sendMessage(plugin.langYml.getMessage("needs-player"))
return
}
if (args.size == 1) {
sender.sendMessage(plugin.langYml.getMessage("needs-pet"))
return
}
val playerName = args[0]
val player = Bukkit.getPlayer(playerName)
if (player == null) {
sender.sendMessage(plugin.langYml.getMessage("invalid-player"))
return
}
val pet = Pets.getByID(args[1])
if (pet == null) {
sender.sendMessage(plugin.langYml.getMessage("invalid-pet"))
return
}
if (!player.hasPet(pet)) {
sender.sendMessage(plugin.langYml.getMessage("doesnt-have-pet"))
return
}
if (player.activePet == pet) {
player.activePet = null
}
player.setPetXP(pet, 0.0)
player.setPetLevel(pet, 0)
sender.sendMessage(
plugin.langYml.getMessage("reset-xp", StringUtils.FormatOption.WITHOUT_PLACEHOLDERS)
.replace("%player%", player.savedDisplayName)
.replace("%pet%", pet.name)
)
}
override fun tabComplete(sender: CommandSender, args: List<String>): List<String> {
if (args.size == 1) {
return Bukkit.getOnlinePlayers().map { it.name }
}
if (args.size == 2) {
return Pets.values().map { it.id }
}
return emptyList()
}
}

View File

@@ -0,0 +1,24 @@
package com.willfp.ecopets.pets
import com.willfp.eco.core.EcoPlugin
import org.bukkit.Bukkit
import org.bukkit.Keyed
import org.bukkit.event.EventHandler
import org.bukkit.event.Listener
import org.bukkit.event.player.PlayerJoinEvent
import org.bukkit.inventory.Recipe
class DiscoverRecipeListener(private val plugin: EcoPlugin) : Listener {
@EventHandler
fun onJoin(event: PlayerJoinEvent) {
if (!plugin.configYml.getBool("discover-recipes")) {
return
}
mutableListOf<Recipe>()
.apply { Bukkit.getServer().recipeIterator().forEachRemaining(this::add) }
.filterIsInstance<Keyed>().map { it.key }
.filter { it.namespace == plugin.name.lowercase() }
.filter { !it.key.contains("displayed") }
.forEach { event.player.discoverRecipe(it) }
}
}

View File

@@ -9,7 +9,6 @@ import com.willfp.eco.core.fast.fast
import com.willfp.eco.core.items.CustomItem import com.willfp.eco.core.items.CustomItem
import com.willfp.eco.core.items.Items import com.willfp.eco.core.items.Items
import com.willfp.eco.core.items.builder.ItemStackBuilder import com.willfp.eco.core.items.builder.ItemStackBuilder
import com.willfp.eco.core.items.builder.SkullBuilder
import com.willfp.eco.core.placeholder.PlayerPlaceholder import com.willfp.eco.core.placeholder.PlayerPlaceholder
import com.willfp.eco.core.placeholder.PlayerStaticPlaceholder import com.willfp.eco.core.placeholder.PlayerStaticPlaceholder
import com.willfp.eco.core.placeholder.PlayerlessPlaceholder import com.willfp.eco.core.placeholder.PlayerlessPlaceholder
@@ -21,6 +20,7 @@ import com.willfp.eco.util.toNiceString
import com.willfp.ecopets.EcoPetsPlugin import com.willfp.ecopets.EcoPetsPlugin
import com.willfp.ecopets.api.event.PlayerPetExpGainEvent import com.willfp.ecopets.api.event.PlayerPetExpGainEvent
import com.willfp.ecopets.api.event.PlayerPetLevelUpEvent import com.willfp.ecopets.api.event.PlayerPetLevelUpEvent
import com.willfp.ecopets.pets.entity.PetEntity
import com.willfp.libreforge.conditions.Conditions import com.willfp.libreforge.conditions.Conditions
import com.willfp.libreforge.conditions.ConfiguredCondition import com.willfp.libreforge.conditions.ConfiguredCondition
import com.willfp.libreforge.effects.ConfiguredEffect import com.willfp.libreforge.effects.ConfiguredEffect
@@ -107,21 +107,19 @@ class Pet(
"${this.id}_spawn_egg", "${this.id}_spawn_egg",
egg, egg,
config.getStrings("spawn-egg.recipe"), config.getStrings("spawn-egg.recipe"),
config.getString("spawn-egg.recipe-permission") config.getStringOrNull("spawn-egg.recipe-permission")
) )
} }
} }
val petEntityItem: ItemStack = SkullBuilder() val entityTexture = config.getString("entity-texture")
.setSkullTexture(config.getString("entity-texture"))
.build()
val levelGUI = PetLevelGUI(plugin, this)
private val levelXpRequirements = listOf(0) + config.getInts("level-xp-requirements") private val levelXpRequirements = listOf(0) + config.getInts("level-xp-requirements")
val maxLevel = levelXpRequirements.size val maxLevel = levelXpRequirements.size
val levelGUI = PetLevelGUI(plugin, this)
private val baseItem: ItemStack = Items.lookup(config.getString("icon")).item private val baseItem: ItemStack = Items.lookup(config.getString("icon")).item
private val effects: Set<ConfiguredEffect> private val effects: Set<ConfiguredEffect>
@@ -153,12 +151,16 @@ class Pet(
private val petXpGains = config.getSubsections("xp-gain-methods").mapNotNull { private val petXpGains = config.getSubsections("xp-gain-methods").mapNotNull {
val trigger = Triggers.getById(it.getString("id")) ?: return@mapNotNull null val trigger = Triggers.getById(it.getString("id")) ?: return@mapNotNull null
val multiplier = it.getDouble("multiplier") val multiplier = it.getDouble("multiplier")
val conditions = it.getSubsections("conditions")
.mapNotNull { cfg -> Conditions.compile(cfg, "Pet $id XP Gain methods") }
PetXPGain( trigger to PetXPGain(
trigger, trigger,
multiplier multiplier,
conditions,
it.getSubsection("filters")
) )
} }.toMap()
init { init {
config.injectPlaceholders( config.injectPlaceholders(
@@ -203,6 +205,13 @@ class Pet(
(it.getPetProgress(this) * 100).toNiceString() (it.getPetProgress(this) * 100).toNiceString()
}.register() }.register()
PlayerPlaceholder(
plugin,
id
) {
it.getPetLevel(this).toString()
}.register()
PlayerPlaceholder( PlayerPlaceholder(
plugin, plugin,
"${id}_current_xp" "${id}_current_xp"
@@ -232,6 +241,10 @@ class Pet(
}.register() }.register()
} }
fun makePetEntity(): PetEntity {
return PetEntity.create(this)
}
fun getLevel(level: Int): PetLevel = levels.get(level) { fun getLevel(level: Int): PetLevel = levels.get(level) {
PetLevel(this, it, effects, conditions) PetLevel(this, it, effects, conditions)
} }
@@ -304,7 +317,14 @@ class Pet(
.map { .map {
it.replace("%percentage_progress%", (player.getPetProgress(this) * 100).toNiceString()) it.replace("%percentage_progress%", (player.getPetProgress(this) * 100).toNiceString())
.replace("%current_xp%", player.getPetXP(this).toNiceString()) .replace("%current_xp%", player.getPetXP(this).toNiceString())
.replace("%required_xp%", this.getExpForLevel(player.getPetLevel(this) + 1).toNiceString()) .replace("%required_xp%", this.getExpForLevel(player.getPetLevel(this) + 1).let { req ->
if (req == Int.MAX_VALUE) {
plugin.langYml.getFormattedString("infinity")
} else {
req.toNiceString()
}
}
)
.replace("%description%", this.description) .replace("%description%", this.description)
.replace("%pet%", this.name) .replace("%pet%", this.name)
.replace("%level%", (forceLevel ?: player.getPetLevel(this)).toString()) .replace("%level%", (forceLevel ?: player.getPetLevel(this)).toString())
@@ -382,12 +402,8 @@ class Pet(
} }
} }
fun canGainXPFromTrigger(trigger: Trigger): Boolean { fun getPetXPGain(trigger: Trigger): PetXPGain? {
return petXpGains.any { it.trigger == trigger } return petXpGains[trigger]
}
fun getTriggerXPMultiplier(trigger: Trigger): Double {
return petXpGains.firstOrNull { it.trigger == trigger }?.multiplier ?: 1.0
} }
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {

View File

@@ -6,23 +6,20 @@ import com.willfp.eco.util.formatEco
import org.bukkit.Bukkit import org.bukkit.Bukkit
import org.bukkit.Location import org.bukkit.Location
import org.bukkit.entity.ArmorStand import org.bukkit.entity.ArmorStand
import org.bukkit.entity.EntityType
import org.bukkit.entity.Player import org.bukkit.entity.Player
import org.bukkit.event.EventHandler import org.bukkit.event.EventHandler
import org.bukkit.event.Listener import org.bukkit.event.Listener
import org.bukkit.event.player.PlayerQuitEvent import org.bukkit.event.player.PlayerQuitEvent
import org.bukkit.inventory.EquipmentSlot
import java.util.* import java.util.*
import kotlin.math.PI import kotlin.math.PI
import kotlin.math.abs import kotlin.math.abs
import kotlin.math.sin
class PetDisplay( class PetDisplay(
private val plugin: EcoPlugin private val plugin: EcoPlugin
) : Listener { ) : Listener {
private var tick = 0 private var tick = 0
private val trackedEntities = mutableMapOf<UUID, ArmorStand>() private val trackedEntities = mutableMapOf<UUID, PetArmorStand>()
fun tickAll() { fun tickAll() {
for (player in Bukkit.getOnlinePlayers()) { for (player in Bukkit.getOnlinePlayers()) {
@@ -37,7 +34,6 @@ class PetDisplay(
val pet = player.activePet val pet = player.activePet
if (pet != null) { if (pet != null) {
stand.equipment?.helmet = pet.petEntityItem
stand.customName = plugin.configYml.getString("pet-entity.name") stand.customName = plugin.configYml.getString("pet-entity.name")
.replace("%player%", player.displayName) .replace("%player%", player.displayName)
.replace("%pet%", pet.name) .replace("%pet%", pet.name)
@@ -49,22 +45,40 @@ class PetDisplay(
location.y += NumberUtils.fastSin(tick / (2 * PI) * 0.5) * 0.15 location.y += NumberUtils.fastSin(tick / (2 * PI) * 0.5) * 0.15
stand.teleport(location) stand.teleport(location)
stand.setRotation((20 * tick / (2 * PI)).toFloat(), 0f)
if (!pet.entityTexture.contains(":")) {
stand.setRotation((20 * tick / (2 * PI)).toFloat(), 0f)
}
} }
} }
private fun getLocation(player: Player): Location { private fun getLocation(player: Player): Location {
val offset = player.eyeLocation.direction.clone().normalize() val offset = player.eyeLocation.direction.clone().normalize()
.multiply(-1) .multiply(-1)
.apply { y = abs(y) } .apply {
y = abs(y)
if (abs(x) < 0.5) {
x = 0.5
}
if (abs(z) < 0.5) {
z = 0.5
}
}
.rotateAroundY(PI / 6) .rotateAroundY(PI / 6)
return player.eyeLocation.clone().add(offset) return player.eyeLocation.clone().add(offset)
} }
private fun getOrNew(player: Player): ArmorStand? { private fun getOrNew(player: Player): ArmorStand? {
val existing = trackedEntities[player.uniqueId] val tracked = trackedEntities[player.uniqueId]
val existing = tracked?.stand
val pet = player.activePet val pet = player.activePet
if (pet != tracked?.pet) {
tracked?.stand?.remove()
}
if (existing == null || existing.isDead || pet == null) { if (existing == null || existing.isDead || pet == null) {
existing?.remove() existing?.remove()
@@ -75,32 +89,17 @@ class PetDisplay(
} }
val location = getLocation(player) val location = getLocation(player)
val newStand = location.world!!.spawnEntity(location, EntityType.ARMOR_STAND) as ArmorStand val stand = pet.makePetEntity().spawn(location)
newStand.isVisible = false
newStand.isInvulnerable = true
newStand.isPersistent = true
newStand.removeWhenFarAway = false
newStand.isSmall = true
newStand.setGravity(false)
newStand.isCollidable = false
for (slot in EquipmentSlot.values()) { trackedEntities[player.uniqueId] = PetArmorStand(stand, pet)
newStand.addEquipmentLock(slot, ArmorStand.LockType.ADDING_OR_CHANGING)
}
newStand.equipment?.helmet = pet.petEntityItem
newStand.isCustomNameVisible = true
newStand.customName = pet.name
trackedEntities[player.uniqueId] = newStand
} }
return trackedEntities[player.uniqueId] return trackedEntities[player.uniqueId]?.stand
} }
fun shutdown() { fun shutdown() {
for (stand in trackedEntities.values) { for (stand in trackedEntities.values) {
stand.remove() stand.stand.remove()
} }
trackedEntities.clear() trackedEntities.clear()
@@ -108,7 +107,12 @@ class PetDisplay(
@EventHandler @EventHandler
fun onLeave(event: PlayerQuitEvent) { fun onLeave(event: PlayerQuitEvent) {
trackedEntities[event.player.uniqueId]?.remove() trackedEntities[event.player.uniqueId]?.stand?.remove()
trackedEntities.remove(event.player.uniqueId) trackedEntities.remove(event.player.uniqueId)
} }
private data class PetArmorStand(
val stand: ArmorStand,
val pet: Pet
)
} }

View File

@@ -9,18 +9,28 @@ import com.willfp.eco.core.gui.slot.MaskItems
import com.willfp.eco.core.items.Items import com.willfp.eco.core.items.Items
import com.willfp.eco.core.items.builder.ItemStackBuilder import com.willfp.eco.core.items.builder.ItemStackBuilder
import com.willfp.eco.util.NumberUtils import com.willfp.eco.util.NumberUtils
import com.willfp.eco.util.toNiceString
import org.bukkit.Material import org.bukkit.Material
import org.bukkit.entity.Player import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack import org.bukkit.inventory.ItemStack
import kotlin.math.ceil import kotlin.math.ceil
import kotlin.math.max import kotlin.math.max
import kotlin.math.min
import kotlin.properties.Delegates
class PetLevelGUI( class PetLevelGUI(
plugin: EcoPlugin, plugin: EcoPlugin,
pet: Pet private val pet: Pet
) { ) {
private val menu: Menu private val menu: Menu
private val pageKey = "page"
private var levelsPerPage by Delegates.notNull<Int>()
private var pages by Delegates.notNull<Int>()
private fun getPage(menu: Menu, player: Player): Int {
val page = menu.getState(player, pageKey) ?: 1
return min(pages, max(page, 1))
}
init { init {
val maskPattern = plugin.configYml.getStrings("level-gui.mask.pattern").toTypedArray() val maskPattern = plugin.configYml.getStrings("level-gui.mask.pattern").toTypedArray()
@@ -51,10 +61,8 @@ class PetLevelGUI(
} }
} }
val pages = ceil(pet.maxLevel.toDouble() / progressionSlots.size).toInt() levelsPerPage = progressionSlots.size
val levelsPerPage = progressionSlots.size pages = ceil(pet.maxLevel.toDouble() / levelsPerPage).toInt()
val pageKey = "page"
menu = menu(plugin.configYml.getInt("level-gui.rows")) { menu = menu(plugin.configYml.getInt("level-gui.rows")) {
setTitle(pet.name) setTitle(pet.name)
@@ -71,7 +79,7 @@ class PetLevelGUI(
value.second, value.second,
slot(ItemStack(Material.BLACK_STAINED_GLASS_PANE)) { slot(ItemStack(Material.BLACK_STAINED_GLASS_PANE)) {
setUpdater { player, menu, _ -> setUpdater { player, menu, _ ->
val page = menu.getState<Int>(player, pageKey) ?: 1 val page = getPage(menu, player)
val slotLevel = ((page - 1) * levelsPerPage) + level val slotLevel = ((page - 1) * levelsPerPage) + level
@@ -126,11 +134,14 @@ class PetLevelGUI(
) { ) {
onLeftClick { event, _, menu -> onLeftClick { event, _, menu ->
val player = event.whoClicked as Player val player = event.whoClicked as Player
var page = menu.getState(player, pageKey) ?: 1 val page = getPage(menu, player)
page--
menu.addState(player, pageKey, page) val newPage = max(0, page - 1)
if (page == 0) {
PetsGUI.open(event.whoClicked as Player) if (newPage == 0) {
PetsGUI.open(player)
} else {
menu.addState(player, pageKey, newPage)
} }
} }
} }
@@ -145,7 +156,11 @@ class PetLevelGUI(
) { ) {
onLeftClick { event, _, menu -> onLeftClick { event, _, menu ->
val player = event.whoClicked as Player val player = event.whoClicked as Player
val newPage = max(pages, (menu.getState(player, pageKey) ?: 1) + 1)
val page = getPage(menu, player)
val newPage = min(pages, page + 1)
menu.addState(player, pageKey, newPage) menu.addState(player, pageKey, newPage)
} }
} }

View File

@@ -1,29 +1,43 @@
package com.willfp.ecopets.pets package com.willfp.ecopets.pets
import com.willfp.eco.core.config.interfaces.Config
import com.willfp.libreforge.conditions.ConfiguredCondition
import com.willfp.libreforge.events.TriggerPreProcessEvent import com.willfp.libreforge.events.TriggerPreProcessEvent
import com.willfp.libreforge.filters.ConfiguredFilter
import com.willfp.libreforge.triggers.Trigger import com.willfp.libreforge.triggers.Trigger
import org.bukkit.event.EventHandler import org.bukkit.event.EventHandler
import org.bukkit.event.Listener import org.bukkit.event.Listener
data class PetXPGain( data class PetXPGain(
val trigger: Trigger, val trigger: Trigger,
val multiplier: Double val multiplier: Double,
val conditions: Iterable<ConfiguredCondition>,
val filters: Config
) )
object PetTriggerXPGainListener: Listener { object PetTriggerXPGainListener : Listener {
@EventHandler(ignoreCancelled = true) @EventHandler(ignoreCancelled = true)
fun handle(event: TriggerPreProcessEvent) { fun handle(event: TriggerPreProcessEvent) {
val player = event.player val player = event.player
val trigger = event.trigger val trigger = event.trigger
val value = event.value val value = event.value
val data = event.data
val pet = event.player.activePet ?: return val pet = event.player.activePet ?: return
if (pet.canGainXPFromTrigger(trigger)) { val xpGain = pet.getPetXPGain(trigger) ?: return
player.givePetExperience(
pet, if (xpGain.conditions.any { !it.isMet(player) }) {
value * pet.getTriggerXPMultiplier(trigger) return
)
} }
if (!ConfiguredFilter(xpGain.filters).matches(data)) {
return
}
player.givePetExperience(
pet,
value * xpGain.multiplier
)
} }
} }

View File

@@ -13,10 +13,24 @@ import org.bukkit.Material
import org.bukkit.Sound import org.bukkit.Sound
import org.bukkit.entity.Player import org.bukkit.entity.Player
import org.bukkit.inventory.ItemStack import org.bukkit.inventory.ItemStack
import kotlin.math.ceil
import kotlin.math.max
import kotlin.math.min
object PetsGUI { object PetsGUI {
private lateinit var menu: Menu private lateinit var menu: Menu
private val petAreaSlots = mutableListOf<Pair<Int, Int>>() private val petAreaSlots = mutableListOf<Pair<Int, Int>>()
private const val pageKey = "page"
private fun getPage(menu: Menu, player: Player): Int {
val pages = ceil(Pets.values()
.filter { player.getPetLevel(it) > 0 }
.size.toDouble() / petAreaSlots.size).toInt()
val page = menu.getState(player, pageKey) ?: 1
return max(min(pages, page + 1), 1)
}
@JvmStatic @JvmStatic
@ConfigUpdater @ConfigUpdater
@@ -27,8 +41,8 @@ object PetsGUI {
val bottomRightColumn = plugin.configYml.getInt("gui.pet-area.bottom-right.column") val bottomRightColumn = plugin.configYml.getInt("gui.pet-area.bottom-right.column")
petAreaSlots.clear() petAreaSlots.clear()
for (column in topLeftColumn..bottomRightColumn) { for (row in topLeftRow..bottomRightRow) {
for (row in topLeftRow..bottomRightRow) { for (column in topLeftColumn..bottomRightColumn) {
petAreaSlots.add(Pair(row, column)) petAreaSlots.add(Pair(row, column))
} }
} }
@@ -50,6 +64,19 @@ object PetsGUI {
} }
} }
val petIconBuilder = { player: Player, menu: Menu, index: Int ->
val page = getPage(menu, player)
val unlockedPets = Pets.values()
.sortedByDescending { player.getPetLevel(it) }
.filter { player.getPetLevel(it) > 0 }
val pagedIndex = ((page - 1) * petAreaSlots.size) + index
val pet = unlockedPets.getOrNull(pagedIndex)
pet?.getIcon(player) ?: ItemStack(Material.AIR)
}
return menu(plugin.configYml.getInt("gui.rows")) { return menu(plugin.configYml.getInt("gui.rows")) {
setTitle(plugin.langYml.getString("menu.title")) setTitle(plugin.langYml.getString("menu.title"))
@@ -74,20 +101,23 @@ object PetsGUI {
for ((index, pair) in petAreaSlots.withIndex()) { for ((index, pair) in petAreaSlots.withIndex()) {
val (row, column) = pair val (row, column) = pair
setSlot(row, column, slot(ItemStack(Material.AIR)) { setSlot(row, column, slot({ p, m -> petIconBuilder(p, m, index) }) {
setUpdater { player, _, _ -> setUpdater { p, m, _ ->
val unlockedPets = Pets.values().filter { player.getPetLevel(it) > 0 } petIconBuilder(p, m, index)
val pet = unlockedPets.getOrNull(index)
pet?.getIcon(player) ?: ItemStack(Material.AIR)
} }
onLeftClick { event, _, _ -> onLeftClick { event, _, _ ->
val player = event.whoClicked as Player val player = event.whoClicked as Player
val page = getPage(menu, player)
val unlockedPets = Pets.values() val unlockedPets = Pets.values()
.sortedByDescending { player.getPetLevel(it) } .sortedByDescending { player.getPetLevel(it) }
.filter { player.getPetLevel(it) > 0 } .filter { player.getPetLevel(it) > 0 }
val pet = unlockedPets.getOrNull(index) ?: return@onLeftClick val pagedIndex = ((page - 1) * petAreaSlots.size) + index
val pet = unlockedPets.getOrNull(pagedIndex) ?: return@onLeftClick
if (player.activePet != pet) { if (player.activePet != pet) {
player.activePet = pet player.activePet = pet
@@ -103,6 +133,49 @@ object PetsGUI {
}) })
} }
setSlot(
plugin.configYml.getInt("gui.prev-page.location.row"),
plugin.configYml.getInt("gui.prev-page.location.column"),
slot(
ItemStackBuilder(Items.lookup(plugin.configYml.getString("gui.prev-page.item")))
.setDisplayName(plugin.configYml.getString("gui.prev-page.name"))
.build()
) {
onLeftClick { event, _, menu ->
val player = event.whoClicked as Player
val page = getPage(menu, player)
val newPage = max(1, page - 1)
menu.addState(player, pageKey, newPage)
}
}
)
setSlot(
plugin.configYml.getInt("gui.next-page.location.row"),
plugin.configYml.getInt("gui.next-page.location.column"),
slot(
ItemStackBuilder(Items.lookup(plugin.configYml.getString("gui.next-page.item")))
.setDisplayName(plugin.configYml.getString("gui.next-page.name"))
.build()
) {
onLeftClick { event, _, menu ->
val player = event.whoClicked as Player
val pages = ceil(Pets.values()
.filter { player.getPetLevel(it) > 0 }
.size.toDouble() / petAreaSlots.size).toInt()
val page = getPage(menu, player)
val newPage = min(pages, page + 1)
menu.addState(player, pageKey, newPage)
}
}
)
setSlot(plugin.configYml.getInt("gui.close.location.row"), setSlot(plugin.configYml.getInt("gui.close.location.row"),
plugin.configYml.getInt("gui.close.location.column"), plugin.configYml.getInt("gui.close.location.column"),
slot( slot(

View File

@@ -0,0 +1,21 @@
package com.willfp.ecopets.pets.entity
import com.ticxo.modelengine.api.ModelEngineAPI
import com.willfp.ecopets.pets.Pet
import org.bukkit.Location
import org.bukkit.entity.ArmorStand
class ModelEnginePetEntity(
pet: Pet,
private val modelID: String
) : PetEntity(pet) {
override fun spawn(location: Location): ArmorStand {
val stand = emptyArmorStandAt(location, pet)
val model = ModelEngineAPI.createActiveModel(modelID)
val modelled = ModelEngineAPI.createModeledEntity(stand)
modelled.addActiveModel(model)
return stand
}
}

View File

@@ -0,0 +1,55 @@
package com.willfp.ecopets.pets.entity
import com.willfp.ecopets.pets.Pet
import org.bukkit.Location
import org.bukkit.entity.ArmorStand
import org.bukkit.entity.EntityType
import org.bukkit.inventory.EquipmentSlot
abstract class PetEntity(
val pet: Pet
) {
abstract fun spawn(location: Location): ArmorStand
companion object {
private val registrations = mutableMapOf<String, (Pet, String) -> PetEntity>()
@JvmStatic
fun registerPetEntity(id: String, parse: (Pet, String) -> PetEntity) {
registrations[id] = parse
}
@JvmStatic
fun create(pet: Pet): PetEntity {
val texture = pet.entityTexture
if (!texture.contains(":")) {
return SkullPetEntity(pet)
}
val id = texture.split(":")[0]
val parse = registrations[id] ?: return SkullPetEntity(pet)
return parse(pet, texture.removePrefix("$id:"))
}
}
}
internal fun emptyArmorStandAt(location: Location, pet: Pet): ArmorStand {
val stand = location.world!!.spawnEntity(location, EntityType.ARMOR_STAND) as ArmorStand
stand.isVisible = false
stand.isInvulnerable = true
stand.isSmall = true
stand.setGravity(false)
stand.isCollidable = false
stand.isPersistent = false
for (slot in EquipmentSlot.values()) {
stand.addEquipmentLock(slot, ArmorStand.LockType.ADDING_OR_CHANGING)
}
stand.isCustomNameVisible = true
stand.customName = pet.name
return stand
}

View File

@@ -0,0 +1,21 @@
package com.willfp.ecopets.pets.entity
import com.willfp.eco.core.items.builder.SkullBuilder
import com.willfp.ecopets.pets.Pet
import org.bukkit.Location
import org.bukkit.entity.ArmorStand
import org.bukkit.inventory.ItemStack
class SkullPetEntity(pet: Pet) : PetEntity(pet) {
override fun spawn(location: Location): ArmorStand {
val stand = emptyArmorStandAt(location, pet)
val skull: ItemStack = SkullBuilder()
.setSkullTexture(pet.entityTexture)
.build()
stand.equipment?.helmet = skull
return stand
}
}

View File

@@ -3,6 +3,8 @@
# by Auxilor # by Auxilor
# #
discover-recipes: true
gui: gui:
rows: 6 rows: 6
@@ -25,7 +27,7 @@ gui:
- "100000001" - "100000001"
- "100000001" - "100000001"
- "100000001" - "100000001"
- "101101111" - "101000111"
pet-area: pet-area:
top-left: top-left:
@@ -86,6 +88,20 @@ gui:
sound: ui_button_click sound: ui_button_click
pitch: 1 pitch: 1
prev-page:
item: arrow
name: "&fPrevious Page"
location:
row: 6
column: 4
next-page:
item: arrow
name: "&fNext Page"
location:
row: 6
column: 6
close: close:
item: barrier item: barrier
name: "&cClose" name: "&cClose"
@@ -202,7 +218,7 @@ level-up:
enabled: true enabled: true
message: message:
- "&f" - "&f"
- " &#d977c2You levelled up your %pet%&#d977c2 petW to &eLevel %level%&#d977c2!" - " &#d977c2You levelled up your %pet%&#d977c2 pet to &eLevel %level%&#d977c2!"
- "&f" - "&f"
- " &#d977c2&lREWARDS:" - " &#d977c2&lREWARDS:"
- " %level_up_messages%" - " %level_up_messages%"

View File

@@ -1,3 +1,3 @@
resource-id: 0 resource-id: 2534
bstats-id: 15502 bstats-id: 15502
color: "&#d977c2" color: "&#d977c2"

View File

@@ -9,13 +9,20 @@ messages:
on-cooldown: "&cThis effect is on cooldown! &fTime left: &a%seconds% seconds" on-cooldown: "&cThis effect is on cooldown! &fTime left: &a%seconds% seconds"
cannot-transmit: "&cYou can't transmit here!" cannot-transmit: "&cYou can't transmit here!"
needs-player: "&cYou must specify a player!" needs-player: "&cYou must specify a player!"
gave-xp: "&fYou have given &a%xp% &fXP to %player%&f's %pet%&f!"
reset-xp: "&fYou have reset %player%&f's %pet%&f XP!"
needs-pet: "&cYou must specify a pet!" needs-pet: "&cYou must specify a pet!"
need-amount: "&cYou must specify a amount!"
invalid-player: "&cInvalid player!" invalid-player: "&cInvalid player!"
invalid-pet: "&cInvalid pet!" invalid-pet: "&cInvalid pet!"
already-has-pet: "&cPlayer already has this pet!" already-has-pet: "&cPlayer already has this pet!"
doesnt-have-pet: "&cPlayer doesn't have this pet!"
gave-pet: "&fSuccessfully gave %player%&f the %pet%&f pet!" gave-pet: "&fSuccessfully gave %player%&f the %pet%&f pet!"
gave-pet-egg: "&fSuccessfully gave %player%&f the %pet%&f pet egg!" gave-pet-egg: "&fSuccessfully gave %player%&f the %pet%&f pet egg!"
cannot-spawn-pet: "&cYou already have this pet unlocked!" cannot-spawn-pet: "&cYou already have this pet unlocked!"
invalid-amount: "&cInvalid amount!"
menu: menu:
title: "Pets" title: "Pets"
infinity: "∞"

View File

@@ -65,6 +65,7 @@ pets:
xp-gain-methods: xp-gain-methods:
- id: melee_attack - id: melee_attack
multiplier: 0.5 multiplier: 0.5
conditions: [ ] # You can add a list of conditions that must be met on xp gain
# Custom placeholders to be used in descriptions, # Custom placeholders to be used in descriptions,
# Don't add % to the IDs, this is done automatically # Don't add % to the IDs, this is done automatically
@@ -110,6 +111,7 @@ pets:
conditions: [ ] conditions: [ ]
# The texture of the pet entity in game # The texture of the pet entity in game
# If you're using modelengine, use modelengine:id as the texture
entity-texture: "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTA5NWZjYzFlM2Q3Y2JkMzUwZjE5YjM4OTQ5OGFiOGJiOTZjNjVhZDE4NWQzNDU5MjA2N2E3ZDAzM2FjNDhkZSJ9fX0=" entity-texture: "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTA5NWZjYzFlM2Q3Y2JkMzUwZjE5YjM4OTQ5OGFiOGJiOTZjNjVhZDE4NWQzNDU5MjA2N2E3ZDAzM2FjNDhkZSJ9fX0="
# The icon in GUIs # The icon in GUIs
@@ -119,7 +121,7 @@ pets:
spawn-egg: spawn-egg:
enabled: true # If the pet should have a spawn egg enabled: true # If the pet should have a spawn egg
item: blaze_spawn_egg unbreaking:1 hide_enchants item: blaze_spawn_egg unbreaking:1 hide_enchants
name: "&6Tiger&f Spawn Egg" name: "&6Tiger&f Pet Spawn Egg"
lore: lore:
- "" - ""
- "&8&oPlace on the ground to" - "&8&oPlace on the ground to"
@@ -127,3 +129,678 @@ pets:
craftable: false craftable: false
recipe: [ ] recipe: [ ]
# recipe-permission: ecopets.craft.tiger # recipe-permission: ecopets.craft.tiger
- id: skeleton
name: "<gradient:#F2F2F2>Skeleton</gradient:#DBDBDB>"
description: "&8&oLevel up by dealing bow damage"
level-xp-requirements:
- 50
- 125
- 200
- 300
- 500
- 750
- 1000
- 1500
- 2000
- 3500
- 5000
- 7500
- 10000
- 15000
- 20000
- 30000
- 50000
- 75000
- 100000
- 200000
- 300000
- 400000
- 500000
- 600000
- 700000
- 800000
- 900000
- 1000000
- 1100000
- 1200000
- 1300000
- 1400000
- 1500000
- 1600000
- 1700000
- 1800000
- 1900000
- 2000000
- 2100000
- 2200000
- 2300000
- 2400000
- 2500000
- 2600000
- 2750000
- 2900000
- 3100000
- 3400000
- 3700000
xp-gain-methods:
- id: bow_attack
multiplier: 0.5
level-placeholders:
- id: "damage_multiplier"
value: "%level%"
effects-description:
1:
- "&8» &8Gives a &a+%damage_multiplier%%&8 bonus to"
- " &8bow damage"
rewards-description:
1:
- "&8» &8Gives a &a+%damage_multiplier%%&8 bonus to"
- " &8bow damage"
level-up-messages:
1:
- "&8» &8Gives a &a+%damage_multiplier%%&8 bonus to"
- " &8bow damage"
level-commands: [ ]
effects:
- id: damage_multiplier
args:
multiplier: "%level% * 0.01 + 1"
triggers:
- bow_attack
conditions: [ ]
entity-texture: "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOWQ0NmViNjQyZGMzYTRkZmJiNWFkNTI5N2VkYWUyOTk2ZWE0Y2ZmZjkyYWMyZWI1NmRmYWU5ZWUxZDU4ZTQwOCJ9fX0="
icon: player_head texture:eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOWQ0NmViNjQyZGMzYTRkZmJiNWFkNTI5N2VkYWUyOTk2ZWE0Y2ZmZjkyYWMyZWI1NmRmYWU5ZWUxZDU4ZTQwOCJ9fX0=
spawn-egg:
enabled: true # If the pet should have a spawn egg
item: skeleton_spawn_egg unbreaking:1 hide_enchants
name: "<gradient:#F2F2F2>Skeleton</gradient:#DBDBDB>&f Pet Spawn Egg"
lore:
- ""
- "&8&oPlace on the ground to"
- "&8&ounlock the &r<gradient:#F2F2F2>Skeleton</gradient:#DBDBDB>&8&o pet!"
craftable: false
recipe: [ ]
- id: ravager
name: "<gradient:#1e3c72>Ravager</gradient:#2a5298>"
description: "&8&oLevel up by successfully defending against village raids"
level-xp-requirements:
- 50
- 150
- 300
- 500
- 750
- 1000
- 1300
- 1650
- 2050
- 2500
- 3000
- 3550
- 4150
- 4800
- 5500
- 6250
- 7050
- 7900
- 8800
- 9750
- 10750
- 11800
- 12900
- 14050
- 15250
- 16500
- 17800
- 19150
- 20550
- 22000
- 23500
- 25050
- 26650
- 28300
- 30000
- 31750
- 33550
- 35400
- 37300
- 39250
- 41250
- 43300
- 45400
- 47550
- 49700
- 51950
- 53250
- 55600
- 57000
xp-gain-methods:
- id: win_raid
multiplier: 50
level-placeholders:
- id: "health_boost"
value: "%level%"
effects-description:
1:
- "&8» &8Gives a &a+%health_boost%%&8 bonus"
rewards-description:
1:
- "&8» &8Gives a &a+%health_boost%%&8 bonus"
level-up-messages:
1:
- "&8» &8Gives a &a+%health_boost%%&8 bonus"
level-commands: [ ]
effects:
- id: bonus_health
args:
health: "%level%"
conditions: [ ]
entity-texture: "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2QyMGJmNTJlYzM5MGEwNzk5Mjk5MTg0ZmM2NzhiZjg0Y2Y3MzJiYjFiZDc4ZmQxYzRiNDQxODU4ZjAyMzVhOCJ9fX0="
icon: player_head texture:eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2QyMGJmNTJlYzM5MGEwNzk5Mjk5MTg0ZmM2NzhiZjg0Y2Y3MzJiYjFiZDc4ZmQxYzRiNDQxODU4ZjAyMzVhOCJ9fX0=
spawn-egg:
enabled: true
item: ravager_spawn_egg unbreaking:1 hide_enchants
name: "<gradient:#1e3c72>Ravager</gradient:#2a5298>&f Pet Spawn Egg"
lore:
- ""
- "&8&oPlace on the ground to"
- "&8&ounlock the &r<gradient:#1e3c72>Ravager</gradient:#2a5298>&8&o pet!"
craftable: false
recipe: [ ]
- id: mancubus
name: "&6Mancubus"
description: "&8&oLevel up by taking damage while on fire"
level-xp-requirements:
- 50
- 125
- 200
- 300
- 500
- 750
- 1000
- 1500
- 2000
- 3500
- 5000
- 7500
- 10000
- 15000
- 20000
- 30000
- 50000
- 75000
- 100000
- 200000
- 300000
- 400000
- 500000
- 600000
- 700000
- 800000
- 900000
- 1000000
- 1100000
- 1200000
- 1300000
- 1400000
- 1500000
- 1600000
- 1700000
- 1800000
- 1900000
- 2000000
- 2100000
- 2200000
- 2300000
- 2400000
- 2500000
- 2600000
- 2750000
- 2900000
- 3100000
- 3400000
- 3700000
xp-gain-methods:
- id: take_damage
multiplier: 0.5
conditions:
- id: on_fire
level-placeholders:
- id: "ignite_chance"
value: "1 - (%level% / 100)"
effects-description:
1:
- "&8» &8Gives a &a+%ignite_chance%%&8 chance to set enemy on fire"
rewards-description:
1:
- "&8» &8Gives a &a+%ignite_chance%%&8 chance to set enemy on fire"
level-up-messages:
1:
- "&8» &8Gives a &a+%ignite_chance%%&8 chance to set enemy on fire"
level-commands: [ ]
effects:
- id: ignite
args:
damage_per_tick: 8
ticks: 300
chance: "%level%"
triggers:
- melee_attack
conditions: [ ]
entity-texture: "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTA5NWZjYzFlM2Q3Y2JkMzUwZjE5YjM4OTQ5OGFiOGJiOTZjNjVhZDE4NWQzNDU5MjA2N2E3ZDAzM2FjNDhkZSJ9fX0="
icon: player_head texture:eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTA5NWZjYzFlM2Q3Y2JkMzUwZjE5YjM4OTQ5OGFiOGJiOTZjNjVhZDE4NWQzNDU5MjA2N2E3ZDAzM2FjNDhkZSJ9fX0=
spawn-egg:
enabled: true # If the pet should have a spawn egg
item: magma_cube_spawn_egg unbreaking:1 hide_enchants
name: "&6Mancubus&f Spawn Egg"
lore:
- ""
- "&8&oPlace on the ground to"
- "&8&ounlock the &r&6Mancubus&8&o pet!"
craftable: false
recipe: [ ]
# recipe-permission: ecopets.craft.mancubus
- id: blaze
name: "&#FF6600Blaze"
description: "&7Earn more XP from killing mobs"
level-xp-requirements:
- 50
- 125
- 200
- 300
- 500
- 750
- 1000
- 1500
- 2000
- 3500
- 5000
- 7500
- 10000
- 15000
- 20000
- 30000
- 50000
- 75000
- 100000
- 200000
- 300000
- 400000
- 500000
- 600000
- 700000
- 800000
- 900000
- 1000000
- 1100000
- 1200000
- 1300000
- 1400000
- 1500000
- 1600000
- 1700000
- 1800000
- 1900000
- 2000000
- 2100000
- 2200000
- 2300000
- 2400000
- 2500000
- 2600000
- 2750000
- 2900000
- 3100000
- 3400000
- 3700000
xp-gain-methods:
- id: kill
multiplier: 1
level-placeholders:
- id: "xp_multiplier"
value: "%level% * 2"
effects-description:
1:
- "&6» &7Increased XP gain by %xp_multiplier%%!"
rewards-description: []
level-up-messages: []
level-commands: []
effects:
- id: xp_multiplier
args:
multiplier: "%level% * 0.02 + 1"
entity-texture: "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjIwNjU3ZTI0YjU2ZTFiMmY4ZmMyMTlkYTFkZTc4OGMwYzI0ZjM2Mzg4YjFhNDA5ZDBjZDJkOGRiYTQ0YWEzYiJ9fX0="
icon: player_head texture:eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYjIwNjU3ZTI0YjU2ZTFiMmY4ZmMyMTlkYTFkZTc4OGMwYzI0ZjM2Mzg4YjFhNDA5ZDBjZDJkOGRiYTQ0YWEzYiJ9fX0=
spawn-egg:
enabled: true # If the pet should have a spawn egg
item: blaze_spawn_egg unbreaking:1 hide_enchants
name: "&#FF6600Blaze &fSpawn Egg"
lore:
- ""
- "&8&oPlace on the ground to"
- "&8&ounlock the &#FF6600Blaze pet!"
craftable: false
recipe: []
recipe-permission: ecopets.craft.blaze
- id: sea_serpent
name: "&9Sea Serpent"
description: "&8&oIncrease swimming speed and damage in water. Level up by swimming"
level-xp-requirements:
- 50
- 125
- 200
- 300
- 500
- 750
- 1000
- 1500
- 2000
- 3500
- 5000
- 7500
- 10000
- 15000
- 20000
- 30000
- 50000
- 75000
- 100000
- 200000
- 300000
- 400000
- 500000
- 600000
- 700000
- 800000
- 900000
- 1000000
- 1100000
- 1200000
- 1300000
- 1400000
- 1500000
- 1600000
- 1700000
- 1800000
- 1900000
- 2000000
- 2100000
- 2200000
- 2300000
- 2400000
- 2500000
- 2600000
- 2750000
- 2900000
- 3100000
- 3400000
- 3700000
- 4000000
- 4500000
xp-gain-methods:
- id: move
multiplier: 0.5
conditions:
- id: is_sprinting
- id: in_water
level-placeholders:
- id: "multiplier"
value: "%level%"
effects-description:
1:
- "&8» &8Gives a &a+%multiplier%%&8 bonus to"
- " &8melee damage when in water"
2:
- "&8» &8Gives a &a+%multiply_velocity%%&8 bonus to"
- " &8movement speed when in water"
rewards-description:
1:
- "&8» &8Gives a &a+%multiplier%%&8 bonus to"
- " &8melee damage when in water"
2:
- "&8» &8Gives a &a+%multiply_velocity%%&8 bonus to"
- " &8movement speed when in water"
level-up-messages:
1:
- "&8» &8Gives a &a+%multiplier%%&8 bonus to"
- " &8melee damage when in water"
2:
- "&8» &8Gives a &a+%multiply_velocity%%&8 bonus to"
- " &8movement speed when in water"
level-commands: [ ]
effects:
- id: damage_multiplier
args:
multiplier: "%level% * 0.01 + 1"
triggers:
- melee_attack
- id: movement_speed_multiplier
args:
multiplier: "%level% * 1.3 + 1"
conditions:
- id: in_water
entity-texture: "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTA5NWZjYzFlM2Q3Y2JkMzUwZjE5YjM4OTQ5OGFiOGJiOTZjNjVhZDE4NWQzNDU5MjA2N2E3ZDAzM2FjNDhkZSJ9fX0="
icon: player_head texture:eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTA5NWZjYzFlM2Q3Y2JkMzUwZjE5YjM4OTQ5OGFiOGJiOTZjNjVhZDE4NWQzNDU5MjA2N2E3ZDAzM2FjNDhkZSJ9fX0=
spawn-egg:
enabled: true # If the pet should have a spawn egg
item: drowned_spawn_egg unbreaking:1 hide_enchants
name: "&9Sea Serpent&f Spawn Egg"
lore:
- ""
- "&8&oPlace on the ground to"
- "&8&ounlock the &r&9Sea Serpent&8&o pet!"
craftable: false
recipe: [ ]
- id: vampire
name: "<gradient:#A50000>Vampire</gradient:#FD2424>"
description: "&8&oLevel up by taking damage at night."
level-xp-requirements:
- 50
- 75
- 100
- 150
- 200
- 300
- 400
- 500
- 750
- 1000
- 1300
- 1500
- 1750
- 2000
- 2300
- 2500
- 3000
- 3500
- 4000
- 4500
- 5000
- 6000
- 8000
- 10000
- 12000
- 15000
- 20000
- 25000
- 30000
- 35000
- 40000
- 44500
- 50000
- 57000
- 64000
- 71000
- 78000
- 80000
- 85000
- 90000
- 95000
- 100000
- 110000
- 115000
- 120000
- 125000
- 150000
- 175000
- 200000
xp-gain-methods:
- id: take_damage
multiplier: 10.0
conditions:
- id: is_night
level-placeholders:
- id: "lifesteal_chance"
value: "%level%"
- id: "lifesteal_cooldown"
value: "1-(%level%/200)"
- id: "lifesteal_heal"
value: "%level%/20"
- id: "bleed_damage"
value: "(%level%-15)/10"
- id: "bleed_chance"
value: "%level%-10"
effects-description:
1:
- "&8» &#ff0000This pet can ONLY be levelled at night."
- ""
- "&8» &7When hitting enemies have a &#ff0000%lifesteal_chance% &7to gain"
- " &7health from your enemy. Has a &#ff0000%lifesteal_cooldown% &7second cooldown."
25:
- "&8» &#ff0000This pet can ONLY be levelled at night."
- ""
- "&8» &7When hitting enemies have a &#ff0000%lifesteal_chance% &7to gain"
- " &7health from your enemy. Has a &#ff0000%lifesteal_cooldown% &7second cooldown."
- ""
- "&8» &7When hitting enemies have a &#ff0000%bleed_chance% &7to bleed"
- " &7your enemies dealing &#ff0000%bleed_damage%&7 damage twice."
rewards-description:
1:
- "&8» &#ff0000This pet can ONLY be levelled at night."
- ""
- "&8» &7When hitting enemies have a &#ff0000%lifesteal_chance% &7to gain &ff0000%lifesteal_heal%"
- " &7health from your enemy. Has a &#ff0000%lifesteal_cooldown% &7second cooldown."
25:
- "&8» &#ff0000This pet can ONLY be levelled at night."
- ""
- "&8» &7When hitting enemies have a &#ff0000%lifesteal_chance% &7to gain"
- " &7health from your enemy. Has a &#ff0000%lifesteal_cooldown% &7second cooldown."
- ""
- "&8» &7When hitting enemies have a &#ff0000%bleed_chance% &7to bleed"
- " &7your enemies dealing &#ff0000%bleed_damage%&7 damage twice."
level-up-messages:
1:
- "&8» &#ff0000This pet can ONLY be levelled at night."
- ""
- "&8» &7When hitting enemies have a &#ff0000%lifesteal_chance% &7to gain"
- " &7health from your enemy. Has a &#ff0000%lifesteal_cooldown% &7second cooldown."
25:
- "&8» &#ff0000This pet can ONLY be levelled at night."
- ""
- "&8» &7When hitting enemies have a &#ff0000%lifesteal_chance% &7to gain"
- " &7health from your enemy. Has a &#ff0000%lifesteal_cooldown% &7second cooldown."
- ""
- "&8» &7When hitting enemies have a &#ff0000%bleed_chance% &7to bleed"
- " &7your enemies dealing &#ff0000%bleed_damage%&7 damage twice."
level-commands: [ ]
effects:
- id: give_health
args:
chance: "%level%"
cooldown: "1-(%level%/200)"
send_cooldown_message: false
amount: "%level%/20"
triggers:
- melee_attack
- id: bleed
args:
chance: "%level%-10"
damage: "(%level%-15)/10"
interval: 15
amount: 2
conditions:
- id: has_pet_level
args:
pet: vampire
level: 25
triggers:
- melee_attack
conditions: []
entity-texture: "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzgyMGExMGRiMjIyZjY5YWMyMjE1ZDdkMTBkY2E0N2VlYWZhMjE1NTUzNzY0YTJiODFiYWZkNDc5ZTc5MzNkMSJ9fX0="
icon: player_head texture:eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzgyMGExMGRiMjIyZjY5YWMyMjE1ZDdkMTBkY2E0N2VlYWZhMjE1NTUzNzY0YTJiODFiYWZkNDc5ZTc5MzNkMSJ9fX0=
spawn-egg:
enabled: true
item: bat_spawn_egg unbreaking:2 hide_enchants
name: "<gradient:#A50000>Vampire</gradient:#FD2424>&f Pet Spawn Egg"
lore:
- ""
- "&8&oPlace on the ground to"
- "&8&ounlock the &r<gradient:#A50000>Vampire</gradient:#FD2424>&8&o pet!"
craftable: false
recipe: [ ]

View File

@@ -23,6 +23,7 @@ softdepend:
- Boosters - Boosters
- EcoSkills - EcoSkills
- Reforges - Reforges
- ModelEngine
commands: commands:
ecopets: ecopets:
description: Base Command description: Base Command
@@ -31,7 +32,8 @@ commands:
aliases: aliases:
- pet - pet
description: Open the pets menu description: Open the pets menu
permission: ecopets.command.skills permission: ecopets.command.pets
default: true
permissions: permissions:
ecopets.*: ecopets.*:
@@ -48,6 +50,8 @@ permissions:
ecopets.command.pets: true ecopets.command.pets: true
ecopets.command.give: true ecopets.command.give: true
ecopets.command.giveegg: true ecopets.command.giveegg: true
ecopets.command.givexp: true
ecopets.command.reset: true
ecopets.command.reload: ecopets.command.reload:
description: Allows reloading the config description: Allows reloading the config
@@ -64,6 +68,12 @@ permissions:
ecopets.command.giveegg: ecopets.command.giveegg:
description: Allows the use of /ecopets giveegg. description: Allows the use of /ecopets giveegg.
default: op default: op
ecopets.command.givexp:
description: Allows the use of /ecopets givexp.
default: op
ecopets.command.reset:
description: Allows the use of /ecopets reset.
default: op
ecopets.xpmultiplier.50percent: ecopets.xpmultiplier.50percent:
description: Gives the player 50% more skill experience description: Gives the player 50% more skill experience

View File

@@ -1,2 +1,4 @@
version=1.0.0 #libreforge-updater
#Sun Jul 24 22:49:45 BST 2022
version=1.13.0
plugin-name=EcoPets plugin-name=EcoPets

0
gradlew vendored Normal file → Executable file
View File