mirror of
https://github.com/Auxilor/EcoQuests.git
synced 2025-12-21 16:09:16 +00:00
Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3ecc004a7f | ||
|
|
252163ba46 | ||
|
|
2a612e84fc | ||
|
|
c9af764714 | ||
|
|
5455db9fda | ||
|
|
3250d33f8e | ||
|
|
c0528c2c81 | ||
|
|
eecbe696a6 | ||
|
|
ba3bc524ae | ||
|
|
b98dd0c6e6 | ||
|
|
93cfb2911a | ||
|
|
d89a50b33b | ||
|
|
ebec6b0615 | ||
|
|
3ca42cb6d8 | ||
|
|
cc3e5af684 | ||
|
|
ddc2659c62 | ||
|
|
406ff65a6d | ||
|
|
e7a16550ac | ||
|
|
63b19f130e | ||
|
|
215e4556cb | ||
|
|
5eeb00c083 | ||
|
|
0a333853d8 | ||
|
|
dd454bd447 |
1
.github/CODEOWNERS
vendored
Normal file
1
.github/CODEOWNERS
vendored
Normal file
@@ -0,0 +1 @@
|
||||
* @WillFP
|
||||
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Discord
|
||||
url: https://discord.gg/ZcwpSsE/
|
||||
about: Issues have moved to Discord, please join the server to get help!
|
||||
11
.github/ISSUE_TEMPLATE/report-a-bug.md
vendored
Normal file
11
.github/ISSUE_TEMPLATE/report-a-bug.md
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
name: Report a Bug
|
||||
about: Report an issue with the plugin
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
# Please report bugs on the discord!
|
||||
|
||||
[Join by clicking here](https://discord.gg/ZcwpSsE/)
|
||||
33
.github/workflows/publish-release.yml
vendored
Normal file
33
.github/workflows/publish-release.yml
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
name: Publish Packages
|
||||
on:
|
||||
workflow_dispatch:
|
||||
release:
|
||||
types: [ created ]
|
||||
push:
|
||||
tags:
|
||||
- '*'
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
- name: Checkout latest code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: 17
|
||||
|
||||
- name: Change wrapper permissions
|
||||
run: chmod +x ./gradlew
|
||||
|
||||
- name: Publish package
|
||||
uses: gradle/gradle-build-action@v2
|
||||
with:
|
||||
arguments: publish
|
||||
env:
|
||||
MAVEN_USERNAME: ${{ secrets.MAVEN_USERNAME }}
|
||||
MAVEN_PASSWORD: ${{ secrets.MAVEN_PASSWORD }}
|
||||
@@ -9,9 +9,23 @@ dependencies {
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
register("maven", MavenPublication::class) {
|
||||
from(components["java"])
|
||||
register<MavenPublication>("maven") {
|
||||
groupId = project.group.toString()
|
||||
version = project.version.toString()
|
||||
artifactId = rootProject.name
|
||||
|
||||
artifact(rootProject.tasks.shadowJar.get().archiveFile)
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
name = "auxilor"
|
||||
url = uri("https://repo.auxilor.io/repository/maven-releases/")
|
||||
credentials {
|
||||
username = System.getenv("MAVEN_USERNAME")
|
||||
password = System.getenv("MAVEN_PASSWORD")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
package com.willfp.ecoquests
|
||||
|
||||
import com.willfp.eco.core.command.impl.PluginCommand
|
||||
import com.willfp.eco.core.data.profile
|
||||
import com.willfp.eco.core.placeholder.PlayerPlaceholder
|
||||
import com.willfp.eco.core.placeholder.PlayerlessPlaceholder
|
||||
import com.willfp.eco.core.placeholder.context.PlaceholderContext
|
||||
import com.willfp.eco.core.placeholder.templates.SimpleInjectablePlaceholder
|
||||
import com.willfp.eco.util.toNiceString
|
||||
import com.willfp.ecoquests.commands.CommandEcoQuests
|
||||
import com.willfp.ecoquests.commands.CommandQuests
|
||||
import com.willfp.ecoquests.gui.PreviousQuestsGUI
|
||||
@@ -12,6 +16,7 @@ import com.willfp.ecoquests.libreforge.ConditionHasCompletedTask
|
||||
import com.willfp.ecoquests.libreforge.ConditionHasQuestActive
|
||||
import com.willfp.ecoquests.libreforge.EffectGainTaskXp
|
||||
import com.willfp.ecoquests.libreforge.EffectGiveTaskXp
|
||||
import com.willfp.ecoquests.libreforge.EffectQuestXpMultiplier
|
||||
import com.willfp.ecoquests.libreforge.EffectStartQuest
|
||||
import com.willfp.ecoquests.libreforge.FilterQuest
|
||||
import com.willfp.ecoquests.libreforge.FilterTask
|
||||
@@ -40,6 +45,7 @@ class EcoQuestsPlugin : LibreforgePlugin() {
|
||||
Conditions.register(ConditionHasQuestActive)
|
||||
Effects.register(EffectGainTaskXp)
|
||||
Effects.register(EffectGiveTaskXp)
|
||||
Effects.register(EffectQuestXpMultiplier)
|
||||
Effects.register(EffectStartQuest)
|
||||
Filters.register(FilterQuest)
|
||||
Filters.register(FilterTask)
|
||||
@@ -56,9 +62,20 @@ class EcoQuestsPlugin : LibreforgePlugin() {
|
||||
Quests.getCompletedQuests(it).size.toString()
|
||||
}.register()
|
||||
|
||||
PlayerPlaceholder(this, "quests_percent_completed") {
|
||||
val completed = Quests.getCompletedQuests(it).size
|
||||
val total = Quests.values().size
|
||||
val percent = completed.toDouble() / total.toDouble() * 100.0
|
||||
percent.toNiceString()
|
||||
}.register()
|
||||
|
||||
PlayerPlaceholder(this, "quests_active") {
|
||||
Quests.getActiveQuests(it).size.toString()
|
||||
}.register()
|
||||
|
||||
PlayerPlaceholder(this, "recent_quest_name") {
|
||||
Quests.getActiveQuests(it).minBy { quest -> quest.getTimeSinceStart(it) }.name
|
||||
}.register()
|
||||
}
|
||||
|
||||
override fun handleReload() {
|
||||
|
||||
@@ -13,6 +13,7 @@ class CommandEcoQuests(plugin: EcoPlugin) : PluginCommand(
|
||||
init {
|
||||
this.addSubcommand(CommandReload(plugin))
|
||||
.addSubcommand(CommandStart(plugin))
|
||||
.addSubcommand(CommandResetPlayer(plugin))
|
||||
.addSubcommand(CommandReset(plugin))
|
||||
}
|
||||
|
||||
|
||||
@@ -3,11 +3,8 @@ package com.willfp.ecoquests.commands
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.core.command.impl.PluginCommand
|
||||
import com.willfp.eco.util.StringUtils
|
||||
import com.willfp.ecoquests.gui.QuestsGUI
|
||||
import com.willfp.ecoquests.quests.Quests
|
||||
import com.willfp.libreforge.commands.CommandReload
|
||||
import org.bukkit.command.CommandSender
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.util.StringUtil
|
||||
|
||||
class CommandReset(plugin: EcoPlugin) : PluginCommand(
|
||||
@@ -17,15 +14,21 @@ class CommandReset(plugin: EcoPlugin) : PluginCommand(
|
||||
false
|
||||
) {
|
||||
override fun onExecute(sender: CommandSender, args: List<String>) {
|
||||
val player = notifyPlayerRequired(args.getOrNull(0), "invalid-player")
|
||||
val quest = notifyNull(Quests[args.getOrNull(1)], "invalid-quest")
|
||||
val quest = notifyNull(Quests[args.getOrNull(0)], "invalid-quest")
|
||||
|
||||
quest.reset(player)
|
||||
if (!quest.isResettable) {
|
||||
sender.sendMessage(
|
||||
plugin.langYml.getMessage("quest-not-resettable", StringUtils.FormatOption.WITHOUT_PLACEHOLDERS)
|
||||
.replace("%quest%", quest.name)
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
quest.reset()
|
||||
|
||||
sender.sendMessage(
|
||||
plugin.langYml.getMessage("reset-quest", StringUtils.FormatOption.WITHOUT_PLACEHOLDERS)
|
||||
.replace("%quest%", quest.name)
|
||||
.replace("%player%", player.name)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -35,14 +38,6 @@ class CommandReset(plugin: EcoPlugin) : PluginCommand(
|
||||
if (args.size == 1) {
|
||||
StringUtil.copyPartialMatches(
|
||||
args[0],
|
||||
plugin.server.onlinePlayers.map { it.name },
|
||||
completions
|
||||
)
|
||||
}
|
||||
|
||||
if (args.size == 2) {
|
||||
StringUtil.copyPartialMatches(
|
||||
args[1],
|
||||
Quests.values().map { it.id },
|
||||
completions
|
||||
)
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.willfp.ecoquests.commands
|
||||
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.core.command.impl.PluginCommand
|
||||
import com.willfp.eco.util.StringUtils
|
||||
import com.willfp.ecoquests.quests.Quests
|
||||
import org.bukkit.command.CommandSender
|
||||
import org.bukkit.util.StringUtil
|
||||
|
||||
class CommandResetPlayer(plugin: EcoPlugin) : PluginCommand(
|
||||
plugin,
|
||||
"resetplayer",
|
||||
"ecoquests.command.resetplayer",
|
||||
false
|
||||
) {
|
||||
override fun onExecute(sender: CommandSender, args: List<String>) {
|
||||
val player = notifyPlayerRequired(args.getOrNull(0), "invalid-player")
|
||||
val quest = notifyNull(Quests[args.getOrNull(1)], "invalid-quest")
|
||||
|
||||
quest.reset(player)
|
||||
|
||||
sender.sendMessage(
|
||||
plugin.langYml.getMessage("reset-quest-for-player", StringUtils.FormatOption.WITHOUT_PLACEHOLDERS)
|
||||
.replace("%quest%", quest.name)
|
||||
.replace("%player%", player.name)
|
||||
)
|
||||
}
|
||||
|
||||
override fun tabComplete(sender: CommandSender, args: List<String>): List<String> {
|
||||
val completions = mutableListOf<String>()
|
||||
|
||||
if (args.size == 1) {
|
||||
StringUtil.copyPartialMatches(
|
||||
args[0],
|
||||
plugin.server.onlinePlayers.map { it.name },
|
||||
completions
|
||||
)
|
||||
}
|
||||
|
||||
if (args.size == 2) {
|
||||
StringUtil.copyPartialMatches(
|
||||
args[1],
|
||||
Quests.values().map { it.id },
|
||||
completions
|
||||
)
|
||||
}
|
||||
|
||||
return completions
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,17 +5,21 @@ import com.willfp.eco.core.gui.onLeftClick
|
||||
import com.willfp.eco.core.gui.slot
|
||||
import com.willfp.eco.core.items.Items
|
||||
import com.willfp.eco.core.items.builder.ItemStackBuilder
|
||||
import com.willfp.eco.core.items.builder.modify
|
||||
import com.willfp.eco.util.formatEco
|
||||
import com.willfp.ecoquests.gui.PreviousQuestsGUI
|
||||
|
||||
class QuestInfoComponent(
|
||||
config: Config
|
||||
) : PositionedComponent {
|
||||
private val slot = slot(
|
||||
ItemStackBuilder(Items.lookup(config.getString("item")))
|
||||
.setDisplayName(config.getFormattedString("name"))
|
||||
.addLoreLines(config.getFormattedStrings("lore"))
|
||||
.build()
|
||||
) {
|
||||
private val baseItem = Items.lookup(config.getString("item"))
|
||||
|
||||
private val slot = slot({ player, _ ->
|
||||
baseItem.item.clone().modify {
|
||||
setDisplayName(config.getString("name").formatEco(player, formatPlaceholders = true))
|
||||
addLoreLines(config.getStrings("lore").formatEco(player, formatPlaceholders = true))
|
||||
}
|
||||
}) {
|
||||
onLeftClick { player, _, _, _ ->
|
||||
PreviousQuestsGUI.open(player)
|
||||
}
|
||||
|
||||
@@ -10,11 +10,14 @@ import org.bukkit.entity.Player
|
||||
|
||||
object ConditionHasCompletedTask : Condition<NoCompileData>("has_completed_task") {
|
||||
override val arguments = arguments {
|
||||
require("quest", "You must specify the quest ID!")
|
||||
require("task", "You must specify the task ID!")
|
||||
}
|
||||
|
||||
override fun isMet(player: Player, config: Config, compileData: NoCompileData): Boolean {
|
||||
val task = Tasks[config.getString("task")] ?: return false
|
||||
val quest = Quests[config.getString("quest")] ?: return false
|
||||
val template = Tasks[config.getString("task")] ?: return false
|
||||
val task = quest.getTask(template) ?: return false
|
||||
|
||||
return task.hasCompleted(player)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.willfp.ecoquests.libreforge
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config
|
||||
import com.willfp.ecoquests.quests.Quests
|
||||
import com.willfp.ecoquests.tasks.Tasks
|
||||
import com.willfp.libreforge.NoCompileData
|
||||
import com.willfp.libreforge.arguments
|
||||
@@ -17,13 +18,17 @@ object EffectGainTaskXp : Effect<NoCompileData>("gain_task_xp") {
|
||||
|
||||
override val arguments = arguments {
|
||||
require("task", "You must specify the task ID!")
|
||||
require("quest", "You must specify the quest ID!")
|
||||
require("xp", "You must specify the amount of xp to gain!")
|
||||
}
|
||||
|
||||
override fun onTrigger(config: Config, data: TriggerData, compileData: NoCompileData): Boolean {
|
||||
val player = data.player ?: return false
|
||||
|
||||
val task = Tasks[config.getString("task")] ?: return false
|
||||
val quest = Quests[config.getString("quest")] ?: return false
|
||||
val template = Tasks[config.getString("task")] ?: return false
|
||||
val task = quest.getTask(template) ?: return false
|
||||
|
||||
val xp = config.getDoubleFromExpression("xp", data)
|
||||
|
||||
task.gainExperience(player, xp)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.willfp.ecoquests.libreforge
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config
|
||||
import com.willfp.ecoquests.quests.Quests
|
||||
import com.willfp.ecoquests.tasks.Tasks
|
||||
import com.willfp.libreforge.NoCompileData
|
||||
import com.willfp.libreforge.arguments
|
||||
@@ -17,13 +18,17 @@ object EffectGiveTaskXp : Effect<NoCompileData>("give_task_xp") {
|
||||
|
||||
override val arguments = arguments {
|
||||
require("task", "You must specify the task ID!")
|
||||
require("quest", "You must specify the quest ID!")
|
||||
require("xp", "You must specify the amount of xp to give!")
|
||||
}
|
||||
|
||||
override fun onTrigger(config: Config, data: TriggerData, compileData: NoCompileData): Boolean {
|
||||
val player = data.player ?: return false
|
||||
|
||||
val task = Tasks[config.getString("task")] ?: return false
|
||||
val quest = Quests[config.getString("quest")] ?: return false
|
||||
val template = Tasks[config.getString("task")] ?: return false
|
||||
val task = quest.getTask(template) ?: return false
|
||||
|
||||
val xp = config.getDoubleFromExpression("xp", data)
|
||||
|
||||
task.giveExperience(player, xp)
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.willfp.ecoquests.libreforge
|
||||
|
||||
import com.willfp.ecoquests.api.event.PlayerTaskExpGainEvent
|
||||
import com.willfp.ecoquests.quests.Quest
|
||||
import com.willfp.ecoquests.quests.Quests
|
||||
import com.willfp.libreforge.effects.templates.MultiMultiplierEffect
|
||||
import org.bukkit.event.EventHandler
|
||||
|
||||
object EffectQuestXpMultiplier : MultiMultiplierEffect<Quest>("quest_xp_multiplier") {
|
||||
override val key = "quests"
|
||||
|
||||
override fun getElement(key: String): Quest? {
|
||||
return Quests[key]
|
||||
}
|
||||
|
||||
override fun getAllElements(): Collection<Quest> {
|
||||
return Quests.values()
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
fun handle(event: PlayerTaskExpGainEvent) {
|
||||
event.amount *= getMultiplier(event.player, event.quest)
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.willfp.ecoquests.libreforge
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config
|
||||
import com.willfp.eco.util.containsIgnoreCase
|
||||
import com.willfp.ecoquests.api.event.QuestEvent
|
||||
import com.willfp.libreforge.NoCompileData
|
||||
import com.willfp.libreforge.filters.Filter
|
||||
@@ -14,8 +15,6 @@ object FilterQuest : Filter<NoCompileData, Collection<String>>("quest") {
|
||||
override fun isMet(data: TriggerData, value: Collection<String>, compileData: NoCompileData): Boolean {
|
||||
val event = data.event as? QuestEvent ?: return true
|
||||
|
||||
return value.any { questID ->
|
||||
questID.equals(event.quest.id, ignoreCase = true)
|
||||
}
|
||||
return value.containsIgnoreCase(event.quest.id)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.willfp.ecoquests.libreforge
|
||||
|
||||
import com.willfp.eco.core.config.interfaces.Config
|
||||
import com.willfp.eco.util.containsIgnoreCase
|
||||
import com.willfp.ecoquests.api.event.QuestEvent
|
||||
import com.willfp.ecoquests.api.event.TaskEvent
|
||||
import com.willfp.libreforge.NoCompileData
|
||||
@@ -15,8 +16,6 @@ object FilterTask : Filter<NoCompileData, Collection<String>>("task") {
|
||||
override fun isMet(data: TriggerData, value: Collection<String>, compileData: NoCompileData): Boolean {
|
||||
val event = data.event as? TaskEvent ?: return true
|
||||
|
||||
return value.any { taskID ->
|
||||
taskID.equals(event.task.id, ignoreCase = true)
|
||||
}
|
||||
return value.containsIgnoreCase(event.task.id)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,20 +14,27 @@ import com.willfp.eco.core.placeholder.PlayerlessPlaceholder
|
||||
import com.willfp.eco.core.placeholder.context.placeholderContext
|
||||
import com.willfp.eco.core.registry.KRegistrable
|
||||
import com.willfp.eco.util.formatEco
|
||||
import com.willfp.eco.util.lineWrap
|
||||
import com.willfp.eco.util.toNiceString
|
||||
import com.willfp.ecoquests.api.event.PlayerQuestCompleteEvent
|
||||
import com.willfp.ecoquests.api.event.PlayerQuestStartEvent
|
||||
import com.willfp.ecoquests.tasks.Task
|
||||
import com.willfp.ecoquests.tasks.TaskTemplate
|
||||
import com.willfp.ecoquests.tasks.Tasks
|
||||
import com.willfp.ecoquests.util.formatDuration
|
||||
import com.willfp.ecoquests.util.randomlyPick
|
||||
import com.willfp.libreforge.EmptyProvidedHolder
|
||||
import com.willfp.libreforge.ViolationContext
|
||||
import com.willfp.libreforge.conditions.Conditions
|
||||
import com.willfp.libreforge.effects.Effects
|
||||
import com.willfp.libreforge.effects.executors.impl.NormalExecutorFactory
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.OfflinePlayer
|
||||
import org.bukkit.entity.Player
|
||||
|
||||
val currentTimeMinutes: Int
|
||||
get() = (System.currentTimeMillis() / 1000 / 60).toInt()
|
||||
|
||||
class Quest(
|
||||
private val plugin: EcoPlugin,
|
||||
override val id: String,
|
||||
@@ -37,6 +44,8 @@ class Quest(
|
||||
|
||||
val announcesStart = config.getBool("announce-start")
|
||||
|
||||
val autoStarts = config.getBool("auto-start")
|
||||
|
||||
private val guiItem = Items.lookup(config.getString("gui.item")).item
|
||||
|
||||
val slot = slot({ player, _ ->
|
||||
@@ -51,6 +60,13 @@ class Quest(
|
||||
addLoreLines(
|
||||
startConditions.getNotMetLines(player, EmptyProvidedHolder)
|
||||
)
|
||||
|
||||
setDisplayName(
|
||||
addPlaceholdersInto(
|
||||
listOf(plugin.configYml.getString("quests.icon.name")),
|
||||
player
|
||||
).first()
|
||||
)
|
||||
}
|
||||
}) {
|
||||
|
||||
@@ -60,22 +76,62 @@ class Quest(
|
||||
|
||||
val alwaysInGUI = config.getBool("gui.always")
|
||||
|
||||
val tasks = config.getStrings("tasks")
|
||||
.mapNotNull { Tasks[it] }
|
||||
.map { Task(plugin, it, this) }
|
||||
// The pool of available tasks to pick from
|
||||
private val availableTasks = config.getSubsections("tasks")
|
||||
.mapNotNull {
|
||||
Tasks[it.getString("task")]
|
||||
?.create(this, it.getString("xp"))
|
||||
}
|
||||
|
||||
private val hasStartedKey: PersistentDataKey<Boolean> = PersistentDataKey(
|
||||
// The amount of tasks to use from the pool
|
||||
val taskAmount = config.getInt("task-amount").let {
|
||||
if (it < 0) {
|
||||
availableTasks.size
|
||||
} else {
|
||||
it.coerceAtMost(availableTasks.size)
|
||||
}
|
||||
}
|
||||
|
||||
private val savedTasksKey = PersistentDataKey(
|
||||
plugin.createNamespacedKey("quest_${id}_tasks"),
|
||||
PersistentDataKeyType.STRING_LIST,
|
||||
emptyList()
|
||||
)
|
||||
|
||||
// The tasks that are actually in use
|
||||
var tasks = run {
|
||||
if (isResettable) {
|
||||
loadTasks() ?: availableTasks.randomlyPick(taskAmount)
|
||||
} else {
|
||||
availableTasks.randomlyPick(taskAmount)
|
||||
}
|
||||
}
|
||||
private set
|
||||
|
||||
private val hasStartedKey = PersistentDataKey(
|
||||
plugin.createNamespacedKey("quest_${id}_has_started"),
|
||||
PersistentDataKeyType.BOOLEAN,
|
||||
false
|
||||
)
|
||||
|
||||
private val hasCompletedKey: PersistentDataKey<Boolean> = PersistentDataKey(
|
||||
private val startedTimeKey = PersistentDataKey(
|
||||
plugin.createNamespacedKey("quest_${id}_started_time"),
|
||||
PersistentDataKeyType.INT,
|
||||
Int.MAX_VALUE
|
||||
)
|
||||
|
||||
private val hasCompletedKey = PersistentDataKey(
|
||||
plugin.createNamespacedKey("quest_${id}_has_completed"),
|
||||
PersistentDataKeyType.BOOLEAN,
|
||||
false
|
||||
)
|
||||
|
||||
private val completedTimeKey = PersistentDataKey(
|
||||
plugin.createNamespacedKey("quest_${id}_completed_time"),
|
||||
PersistentDataKeyType.INT,
|
||||
Int.MAX_VALUE
|
||||
)
|
||||
|
||||
private val rewardMessages = config.getStrings("reward-messages")
|
||||
|
||||
private val rewards = Effects.compileChain(
|
||||
@@ -103,14 +159,16 @@ class Quest(
|
||||
|
||||
private val resetTime = config.getInt("reset-time")
|
||||
|
||||
val isResettable: Boolean
|
||||
get() = resetTime >= 0
|
||||
|
||||
val minutesUntilReset: Int
|
||||
get() = if (resetTime < 0) {
|
||||
Int.MAX_VALUE
|
||||
} else {
|
||||
val currentTime = (System.currentTimeMillis() / 1000 / 60).toInt()
|
||||
val previousTime = ServerProfile.load().read(lastResetTimeKey)
|
||||
|
||||
resetTime - currentTime + previousTime
|
||||
resetTime - currentTimeMinutes + previousTime
|
||||
}
|
||||
|
||||
init {
|
||||
@@ -141,17 +199,60 @@ class Quest(
|
||||
PlayerlessPlaceholder(plugin, "quest_${id}_time_until_reset") {
|
||||
formatDuration(this.minutesUntilReset)
|
||||
}.register()
|
||||
|
||||
PlayerPlaceholder(plugin, "quest_${id}_time_since_start") {
|
||||
formatDuration(this.getTimeSinceStart(it))
|
||||
}.register()
|
||||
|
||||
PlayerPlaceholder(plugin, "quest_${id}_time_since_completed") {
|
||||
formatDuration(this.getTimeSinceCompletion(it))
|
||||
}.register()
|
||||
|
||||
PlayerPlaceholder(plugin, "quest_${id}_time_since") {
|
||||
if (hasCompleted(it)) {
|
||||
plugin.langYml.getString("time-since.completed")
|
||||
.replace("%time%", formatDuration(this.getTimeSinceCompletion(it)))
|
||||
.formatEco(it)
|
||||
} else if (hasStarted(it)) {
|
||||
plugin.langYml.getString("time-since.started")
|
||||
.replace("%time%", formatDuration(this.getTimeSinceStart(it)))
|
||||
.formatEco(it)
|
||||
} else {
|
||||
plugin.langYml.getString("time-since.never")
|
||||
.formatEco(it)
|
||||
}
|
||||
}.register()
|
||||
}
|
||||
|
||||
override fun onRegister() {
|
||||
for (task in tasks) {
|
||||
task.bind()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRemove() {
|
||||
if (isResettable) {
|
||||
saveTasks()
|
||||
}
|
||||
|
||||
for (task in tasks) {
|
||||
task.unbind()
|
||||
}
|
||||
}
|
||||
|
||||
fun getTask(template: TaskTemplate): Task? {
|
||||
return tasks.firstOrNull { it.template == template }
|
||||
}
|
||||
|
||||
fun getDescription(player: Player): List<String> {
|
||||
return addPlaceholdersInto(listOf(config.getString("description")), player)
|
||||
}
|
||||
|
||||
fun hasActive(player: Player): Boolean {
|
||||
fun hasActive(player: OfflinePlayer): Boolean {
|
||||
return hasStarted(player) && !hasCompleted(player)
|
||||
}
|
||||
|
||||
fun hasCompleted(player: Player): Boolean {
|
||||
fun hasCompleted(player: OfflinePlayer): Boolean {
|
||||
return player.profile.read(hasCompletedKey)
|
||||
}
|
||||
|
||||
@@ -160,14 +261,14 @@ class Quest(
|
||||
}
|
||||
|
||||
fun shouldStart(player: Player): Boolean {
|
||||
return meetsStartConditions(player) && !hasStarted(player)
|
||||
return meetsStartConditions(player) && !hasStarted(player) && autoStarts
|
||||
}
|
||||
|
||||
fun hasStarted(player: Player): Boolean {
|
||||
fun hasStarted(player: OfflinePlayer): Boolean {
|
||||
return player.profile.read(hasStartedKey)
|
||||
}
|
||||
|
||||
fun reset(player: Player) {
|
||||
fun reset(player: OfflinePlayer) {
|
||||
player.profile.write(hasStartedKey, false)
|
||||
player.profile.write(hasCompletedKey, false)
|
||||
|
||||
@@ -183,10 +284,34 @@ class Quest(
|
||||
|
||||
startEffects?.trigger(player)
|
||||
player.profile.write(hasStartedKey, true)
|
||||
player.profile.write(startedTimeKey, currentTimeMinutes)
|
||||
|
||||
Bukkit.getPluginManager().callEvent(PlayerQuestStartEvent(player, this))
|
||||
}
|
||||
|
||||
fun getTimeSinceStart(player: OfflinePlayer): Int {
|
||||
return currentTimeMinutes - player.profile.read(startedTimeKey)
|
||||
}
|
||||
|
||||
fun getTimeSinceCompletion(player: OfflinePlayer): Int {
|
||||
return currentTimeMinutes - player.profile.read(completedTimeKey)
|
||||
}
|
||||
|
||||
fun getTimeSincePlaceholder(player: Player): String {
|
||||
return if (hasCompleted(player)) {
|
||||
plugin.langYml.getString("time-since.completed")
|
||||
.replace("%time%", formatDuration(this.getTimeSinceCompletion(player)))
|
||||
.formatEco(player)
|
||||
} else if (hasStarted(player)) {
|
||||
plugin.langYml.getString("time-since.started")
|
||||
.replace("%time%", formatDuration(this.getTimeSinceStart(player)))
|
||||
.formatEco(player)
|
||||
} else {
|
||||
plugin.langYml.getString("time-since.never")
|
||||
.formatEco(player)
|
||||
}
|
||||
}
|
||||
|
||||
fun resetIfNeeded() {
|
||||
if (resetTime < 0) {
|
||||
return
|
||||
@@ -196,11 +321,69 @@ class Quest(
|
||||
return
|
||||
}
|
||||
|
||||
reset()
|
||||
}
|
||||
|
||||
fun reset() {
|
||||
ServerProfile.load().write(lastResetTimeKey, (System.currentTimeMillis() / 1000 / 60).toInt())
|
||||
|
||||
for (player in Bukkit.getOnlinePlayers()) {
|
||||
reset(player)
|
||||
}
|
||||
|
||||
// Offline players can be reset async
|
||||
plugin.scheduler.runAsync {
|
||||
for (player in Bukkit.getOfflinePlayers()) {
|
||||
if (!player.isOnline) {
|
||||
reset(player)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Unbind old tasks
|
||||
for (task in tasks) {
|
||||
task.unbind()
|
||||
}
|
||||
|
||||
tasks = availableTasks.randomlyPick(taskAmount)
|
||||
|
||||
// Bind new tasks
|
||||
for (task in tasks) {
|
||||
task.bind()
|
||||
}
|
||||
|
||||
// Save new tasks
|
||||
saveTasks()
|
||||
}
|
||||
|
||||
private fun loadTasks(): List<Task>? {
|
||||
val serialized = ServerProfile.load().read(savedTasksKey)
|
||||
|
||||
if (serialized.isEmpty()) {
|
||||
return null
|
||||
}
|
||||
|
||||
val savedTasks = mutableListOf<Task>()
|
||||
|
||||
for (s in serialized) {
|
||||
val split = s.split(":")
|
||||
val taskId = split[0]
|
||||
val xpExpr = split[1]
|
||||
|
||||
val template = Tasks[taskId] ?: continue
|
||||
|
||||
savedTasks += template.create(this, xpExpr)
|
||||
}
|
||||
|
||||
return savedTasks
|
||||
}
|
||||
|
||||
private fun saveTasks() {
|
||||
val serialized = tasks.map {
|
||||
"${it.template.id}:${it.xpExpr}"
|
||||
}
|
||||
|
||||
ServerProfile.load().write(savedTasksKey, serialized)
|
||||
}
|
||||
|
||||
fun checkCompletion(player: Player): Boolean {
|
||||
@@ -210,17 +393,21 @@ class Quest(
|
||||
}
|
||||
|
||||
if (tasks.all { it.hasCompleted(player) }) {
|
||||
player.profile.write(hasCompletedKey, true)
|
||||
rewards?.trigger(player)
|
||||
|
||||
Bukkit.getPluginManager().callEvent(PlayerQuestCompleteEvent(player, this))
|
||||
|
||||
complete(player)
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private fun complete(player: Player) {
|
||||
player.profile.write(hasCompletedKey, true)
|
||||
player.profile.write(completedTimeKey, currentTimeMinutes)
|
||||
rewards?.trigger(player)
|
||||
|
||||
Bukkit.getPluginManager().callEvent(PlayerQuestCompleteEvent(player, this))
|
||||
}
|
||||
|
||||
private fun List<String>.addMargin(margin: Int): List<String> {
|
||||
return this.map { s -> " ".repeat(margin) + s }
|
||||
}
|
||||
@@ -233,6 +420,7 @@ class Quest(
|
||||
fun String.addPlaceholders() = this
|
||||
.replace("%quest%", quest.name)
|
||||
.replace("%time_until_reset%", formatDuration(quest.minutesUntilReset))
|
||||
.replace("%time_since%", getTimeSincePlaceholder(player))
|
||||
|
||||
// Replace multi-line placeholders.
|
||||
val processed = strings.flatMap { s ->
|
||||
@@ -242,7 +430,7 @@ class Quest(
|
||||
rewardMessages
|
||||
.addMargin(margin)
|
||||
} else if (s.contains("%tasks%")) {
|
||||
tasks.flatMap { task -> task.getCompletedDescription(player) }
|
||||
tasks.map { task -> task.getCompletedDescription(player) }
|
||||
.addMargin(margin)
|
||||
} else if (s.contains("%description%")) {
|
||||
getDescription(player)
|
||||
@@ -256,6 +444,6 @@ class Quest(
|
||||
placeholderContext(
|
||||
player = player
|
||||
)
|
||||
)
|
||||
).lineWrap(plugin.configYml.getInt("quests.icon.line-wrap"), true)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import com.willfp.eco.core.data.keys.PersistentDataKey
|
||||
import com.willfp.eco.core.data.keys.PersistentDataKeyType
|
||||
import com.willfp.eco.core.data.profile
|
||||
import com.willfp.eco.core.placeholder.PlayerPlaceholder
|
||||
import com.willfp.eco.core.placeholder.PlayerlessPlaceholder
|
||||
import com.willfp.eco.core.placeholder.context.placeholderContext
|
||||
import com.willfp.eco.util.evaluateExpression
|
||||
import com.willfp.eco.util.formatEco
|
||||
@@ -17,6 +16,7 @@ import com.willfp.ecoquests.quests.Quest
|
||||
import com.willfp.ecoquests.quests.Quests
|
||||
import com.willfp.libreforge.counters.Accumulator
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.OfflinePlayer
|
||||
import org.bukkit.entity.Player
|
||||
import kotlin.math.min
|
||||
|
||||
@@ -24,7 +24,7 @@ class Task(
|
||||
private val plugin: EcoPlugin,
|
||||
val template: TaskTemplate,
|
||||
val quest: Quest,
|
||||
private val xpExpr: String
|
||||
internal val xpExpr: String
|
||||
) {
|
||||
private val xpKey = PersistentDataKey(
|
||||
plugin.createNamespacedKey("${quest.id}_task_${template.id}_xp"),
|
||||
@@ -80,12 +80,12 @@ class Task(
|
||||
}
|
||||
}
|
||||
|
||||
fun reset(player: Player) {
|
||||
fun reset(player: OfflinePlayer) {
|
||||
player.profile.write(xpKey, 0.0)
|
||||
player.profile.write(hasCompletedKey, false)
|
||||
}
|
||||
|
||||
fun hasCompleted(player: Player): Boolean {
|
||||
fun hasCompleted(player: OfflinePlayer): Boolean {
|
||||
return player.profile.read(hasCompletedKey)
|
||||
}
|
||||
|
||||
@@ -98,8 +98,8 @@ class Task(
|
||||
)
|
||||
}
|
||||
|
||||
fun getExperience(player: Player): Double {
|
||||
return min(player.profile.read(xpKey), getExperienceRequired(player))
|
||||
fun getExperience(player: OfflinePlayer): Double {
|
||||
return player.profile.read(xpKey)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -124,7 +124,7 @@ class Task(
|
||||
val requiredXp = getExperienceRequired(player)
|
||||
val newXp = player.profile.read(xpKey) + amount
|
||||
|
||||
player.profile.write(xpKey, newXp)
|
||||
player.profile.write(xpKey, min(newXp, requiredXp))
|
||||
|
||||
if (newXp >= requiredXp) {
|
||||
player.profile.write(hasCompletedKey, true)
|
||||
@@ -145,15 +145,13 @@ class Task(
|
||||
.formatEco(player)
|
||||
}
|
||||
|
||||
fun getCompletedDescription(player: Player): List<String> {
|
||||
fun getCompletedDescription(player: Player): String {
|
||||
return if (hasCompleted(player)) {
|
||||
plugin.configYml.getString("tasks.completed")
|
||||
.replace("%description%", getDescription(player))
|
||||
.lineWrap(plugin.configYml.getInt("tasks.line-wrap"), true)
|
||||
} else {
|
||||
plugin.configYml.getString("tasks.not-completed")
|
||||
.replace("%description%", getDescription(player))
|
||||
.lineWrap(plugin.configYml.getInt("tasks.line-wrap"), true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.willfp.ecoquests.tasks
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.core.config.interfaces.Config
|
||||
import com.willfp.eco.core.registry.KRegistrable
|
||||
import com.willfp.ecoquests.quests.Quest
|
||||
import com.willfp.libreforge.ViolationContext
|
||||
import com.willfp.libreforge.counters.Counters
|
||||
|
||||
@@ -14,4 +15,7 @@ class TaskTemplate(
|
||||
val xpGainMethods = config.getSubsections("xp-gain-methods").mapNotNull {
|
||||
Counters.compile(it, ViolationContext(plugin, "task $id tasks"))
|
||||
}
|
||||
|
||||
fun create(quest: Quest, xpExpr: String) =
|
||||
Task(plugin, this, quest, xpExpr)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package com.willfp.ecoquests.util
|
||||
|
||||
fun <T> Collection<T>.randomlyPick(amount: Int): List<T> {
|
||||
val list = this.toMutableList()
|
||||
val picked = mutableListOf<T>()
|
||||
|
||||
repeat(amount) {
|
||||
val index = (0 until list.size).random()
|
||||
picked.add(list[index])
|
||||
list.removeAt(index)
|
||||
}
|
||||
|
||||
return picked
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
# by Auxilor
|
||||
#
|
||||
|
||||
scan-interval: 20 # How often to scan for quest starting / completion (in ticks)
|
||||
scan-interval: 20 # How often to scan for quests auto-starting (in ticks)
|
||||
|
||||
gui:
|
||||
title: "Quest Book"
|
||||
@@ -34,10 +34,13 @@ gui:
|
||||
|
||||
quest-info:
|
||||
item: writable_book
|
||||
name: "&aQuest Book"
|
||||
name: "&fQuest Book"
|
||||
lore:
|
||||
- "&eClick to view your"
|
||||
- "&eprevious quests!"
|
||||
- ""
|
||||
- "&7Quests Completed: &f%ecoquests_quests_completed%"
|
||||
- "&7Quests Active: &f%ecoquests_quests_active%"
|
||||
- ""
|
||||
- "&eClick to view past quests!"
|
||||
|
||||
location:
|
||||
row: 1
|
||||
@@ -130,12 +133,15 @@ completed-gui:
|
||||
custom-slots: [ ]
|
||||
|
||||
tasks:
|
||||
line-wrap: 32
|
||||
completed: "&a&l✓ &r&f%description%"
|
||||
not-completed: "&c&l✘ &r&f%description%"
|
||||
# The line to show when a task is completed
|
||||
completed: "&a&l✔ &r&f%description%"
|
||||
# The line to show when a task is not completed
|
||||
not-completed: "&c&l❌ &r&f%description%"
|
||||
|
||||
quests:
|
||||
icon:
|
||||
name: "&e%quest%" # The name of the icon
|
||||
line-wrap: 32 # Lore line-wrapping
|
||||
lore:
|
||||
- "%description%"
|
||||
- ""
|
||||
@@ -144,6 +150,8 @@ quests:
|
||||
- ""
|
||||
- "&fRewards:"
|
||||
- " %rewards%"
|
||||
- ""
|
||||
- "%time_since%"
|
||||
|
||||
complete:
|
||||
message:
|
||||
|
||||
@@ -10,4 +10,11 @@ messages:
|
||||
already-started: "&cThe player has already started this quest!"
|
||||
|
||||
started-quest: "&fStarted the &a%quest% &fquest for &a%player%&f!"
|
||||
reset-quest: "&fReset the &a%quest% &fquest for &a%player%&f!"
|
||||
reset-quest-for-player: "&fReset the &a%quest% &fquest for &a%player%&f!"
|
||||
reset-quest: "&fReset the &a%quest% &fquest!"
|
||||
quest-not-resettable: "&cThis quest is not resettable!"
|
||||
|
||||
time-since:
|
||||
never: "&cNot started yet!"
|
||||
started: "&7Started %time% ago"
|
||||
completed: "&7Completed %time% ago"
|
||||
|
||||
@@ -15,3 +15,38 @@ dependencies:
|
||||
load-after:
|
||||
- name: eco
|
||||
bootstrap: false
|
||||
|
||||
permissions:
|
||||
ecoquests.*:
|
||||
description: All ecoquests permissions
|
||||
default: op
|
||||
children:
|
||||
ecoquests.command.*: true
|
||||
ecoquests.command.*:
|
||||
description: All commands
|
||||
default: op
|
||||
children:
|
||||
ecoquests.command.reload: true
|
||||
ecoquests.command.quests: true
|
||||
ecoquests.command.start: true
|
||||
ecoquests.command.reset: true
|
||||
ecoquests.command.resetplayer: true
|
||||
|
||||
ecoquests.command.reload:
|
||||
description: Allows reloading the config
|
||||
default: op
|
||||
ecoquests.command.ecoquests:
|
||||
description: Allows the use of /ecoquests.
|
||||
default: true
|
||||
ecoquests.command.quests:
|
||||
description: Allows the use of /quests.
|
||||
default: true
|
||||
ecoquests.command.start:
|
||||
description: Allows using /ecoquests start.
|
||||
default: op
|
||||
ecoquests.command.reset:
|
||||
description: Allows using /ecoquests reset.
|
||||
default: op
|
||||
ecoquests.command.resetplayer:
|
||||
description: Allows using /ecoquests resetplayer.
|
||||
default: op
|
||||
|
||||
@@ -32,8 +32,9 @@ permissions:
|
||||
children:
|
||||
ecoquests.command.reload: true
|
||||
ecoquests.command.quests: true
|
||||
ecoquests.command.start: op
|
||||
ecoquests.command.reset: op
|
||||
ecoquests.command.start: true
|
||||
ecoquests.command.reset: true
|
||||
ecoquests.command.resetplayer: true
|
||||
|
||||
ecoquests.command.reload:
|
||||
description: Allows reloading the config
|
||||
@@ -49,4 +50,7 @@ permissions:
|
||||
default: op
|
||||
ecoquests.command.reset:
|
||||
description: Allows using /ecoquests reset.
|
||||
default: op
|
||||
ecoquests.command.resetplayer:
|
||||
description: Allows using /ecoquests resetplayer.
|
||||
default: op
|
||||
@@ -1,26 +1,36 @@
|
||||
name: "Resettable Quest"
|
||||
# The ID of the quest is the name of the .yml file,
|
||||
# for example traveller.yml has the ID of traveller
|
||||
# You can place quests anywhere in this folder,
|
||||
# including in subfolders if you want to organize your quest configs
|
||||
# _example.yml is not loaded.
|
||||
|
||||
description: "&fThis quest will reset in &a%time_until_reset%"
|
||||
name: "Traveller"
|
||||
|
||||
description: "&7Stretch your legs! Walk around Lumoria and find new places to explore."
|
||||
|
||||
# Options for the /quests GUI
|
||||
gui:
|
||||
enabled: true # If the quest should be shown in the GUI
|
||||
always: false # If the quest should always be in the GUI, even if it's not started
|
||||
# The item to show in the GUI, read https://plugins.auxilor.io/all-plugins/the-item-lookup-system
|
||||
item: paper name:"&eExample Quest"
|
||||
item: paper
|
||||
|
||||
# How many minutes between this quest being reset (set to -1 to disable)
|
||||
# 1 Day: 1440
|
||||
# 1 Week: 10080
|
||||
# 1 Month: 43200
|
||||
reset-time: 10
|
||||
reset-time: -1
|
||||
|
||||
# A list of tasks and their XP requirements to complete this quest.
|
||||
# If the task is one action, set XP to 1.
|
||||
# XP requirements can use placeholder math, for example %ecoskills_combat% * 100
|
||||
tasks:
|
||||
- task: break_stone
|
||||
xp: 100
|
||||
- task: move
|
||||
xp: 1000
|
||||
|
||||
# (For resettable tasks) The amount of tasks to select from the list above.
|
||||
# Set to -1 to use all tasks.
|
||||
task-amount: -1
|
||||
|
||||
# The messages for the %rewards% placeholder in icons, messages, etc.
|
||||
reward-messages:
|
||||
@@ -40,4 +50,9 @@ start-effects: [ ]
|
||||
# A list of conditions required to start the quest.
|
||||
# The quest will be automatically started when these conditions are met.
|
||||
# Read https://plugins.auxilor.io/conditions/configuring-a-condition
|
||||
# If gui.always is true, then not-met-lines will show up on the GUI icon!
|
||||
start-conditions: [ ]
|
||||
|
||||
# If the quest should auto start when all conditions are met
|
||||
# If this is set to false, the quest can only be started with /ecoquests start
|
||||
auto-start: true
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
name: "Resettable Quest"
|
||||
name: "Daily Quest I"
|
||||
|
||||
description: "&fThis quest will reset in &a%time_until_reset%"
|
||||
|
||||
@@ -7,13 +7,13 @@ gui:
|
||||
enabled: true # If the quest should be shown in the GUI
|
||||
always: false # If the quest should always be in the GUI, even if it's not started
|
||||
# The item to show in the GUI, read https://plugins.auxilor.io/all-plugins/the-item-lookup-system
|
||||
item: paper name:"&eExample Quest"
|
||||
item: paper
|
||||
|
||||
# How many minutes between this quest being reset (set to -1 to disable)
|
||||
# 1 Day: 1440
|
||||
# 1 Week: 10080
|
||||
# 1 Month: 43200
|
||||
reset-time: 10
|
||||
reset-time: 1440
|
||||
|
||||
# A list of tasks and their XP requirements to complete this quest.
|
||||
# If the task is one action, set XP to 1.
|
||||
@@ -22,6 +22,10 @@ tasks:
|
||||
- task: break_stone
|
||||
xp: 100
|
||||
|
||||
# (For resettable tasks) The amount of tasks to select from the list above.
|
||||
# Set to -1 to use all tasks.
|
||||
task-amount: 1
|
||||
|
||||
# The messages for the %rewards% placeholder in icons, messages, etc.
|
||||
reward-messages:
|
||||
- " &8» &r&f+2 %ecoskills_defense_name%"
|
||||
@@ -40,4 +44,7 @@ start-effects: [ ]
|
||||
# A list of conditions required to start the quest.
|
||||
# The quest will be automatically started when these conditions are met.
|
||||
# Read https://plugins.auxilor.io/conditions/configuring-a-condition
|
||||
# If gui.always is true, then not-met-lines will show up on the GUI icon!
|
||||
start-conditions: [ ]
|
||||
|
||||
auto-start: true
|
||||
@@ -1,7 +1,7 @@
|
||||
# The ID of the task is the name of the .yml file,
|
||||
# for example break_100_stone.yml has the ID of break_100_stone
|
||||
# You can place tasks anywhere in this folder,
|
||||
# including in subfolders if you want to organize your quest task
|
||||
# including in subfolders if you want to organize your task configs
|
||||
# _example.yml is not loaded.
|
||||
|
||||
# If multiple quests have the same task, gaining task XP for one quest
|
||||
|
||||
4
eco-core/core-plugin/src/main/resources/tasks/move.yml
Normal file
4
eco-core/core-plugin/src/main/resources/tasks/move.yml
Normal file
@@ -0,0 +1,4 @@
|
||||
description: "&fMove distance (&a%xp%&8/&a%required-xp%&f)"
|
||||
|
||||
xp-gain-methods:
|
||||
- trigger: move
|
||||
@@ -1,5 +1,5 @@
|
||||
#libreforge-updater
|
||||
#Wed Aug 09 14:37:41 BST 2023
|
||||
kotlin.code.style=official
|
||||
libreforge-version=4.27.0
|
||||
version=0.3.0
|
||||
libreforge-version=4.28.0
|
||||
version=1.0.0
|
||||
|
||||
Reference in New Issue
Block a user