From 28c3826c35f07df2203d0879017b5be6fa3f5d24 Mon Sep 17 00:00:00 2001 From: LMBishop <13875753+LMBishop@users.noreply.github.com> Date: Wed, 17 Feb 2021 01:09:46 +0000 Subject: Add started menu --- .../quests/commands/CommandQuests.java | 7 +- .../quests/events/EventInventory.java | 82 +++++++--- .../java/com/leonardobishop/quests/obj/Items.java | 1 + .../com/leonardobishop/quests/obj/Options.java | 1 + .../com/leonardobishop/quests/obj/misc/QMenu.java | 2 + .../quests/obj/misc/QMenuCancel.java | 8 +- .../quests/obj/misc/QMenuStarted.java | 176 +++++++++++++++++++++ .../quests/obj/misc/QuestSortWrapper.java | 44 ++++++ .../com/leonardobishop/quests/player/QPlayer.java | 24 ++- .../com/leonardobishop/quests/quests/Quest.java | 4 + src/main/resources/config.yml | 6 + 11 files changed, 324 insertions(+), 31 deletions(-) create mode 100644 src/main/java/com/leonardobishop/quests/obj/misc/QMenuStarted.java create mode 100644 src/main/java/com/leonardobishop/quests/obj/misc/QuestSortWrapper.java (limited to 'src') diff --git a/src/main/java/com/leonardobishop/quests/commands/CommandQuests.java b/src/main/java/com/leonardobishop/quests/commands/CommandQuests.java index ca64aa3f..d88ca70f 100644 --- a/src/main/java/com/leonardobishop/quests/commands/CommandQuests.java +++ b/src/main/java/com/leonardobishop/quests/commands/CommandQuests.java @@ -410,6 +410,11 @@ public class CommandQuests implements TabExecutor { } return true; } + } else if (sender instanceof Player && (args[0].equalsIgnoreCase("started"))) { + Player player = (Player) sender; + QPlayer qPlayer = plugin.getPlayerManager().getPlayer(player.getUniqueId()); + qPlayer.openStartedQuests(); + return true; } showHelp(sender); } else { @@ -553,7 +558,7 @@ public class CommandQuests implements TabExecutor { } if (sender instanceof Player) { if (args.length == 1) { - List options = new ArrayList<>(Arrays.asList("quest", "category")); + List options = new ArrayList<>(Arrays.asList("quest", "category", "started")); if (sender.hasPermission("quests.admin")) { options.add("admin"); } diff --git a/src/main/java/com/leonardobishop/quests/events/EventInventory.java b/src/main/java/com/leonardobishop/quests/events/EventInventory.java index 18b14ef3..e1c4d0c2 100644 --- a/src/main/java/com/leonardobishop/quests/events/EventInventory.java +++ b/src/main/java/com/leonardobishop/quests/events/EventInventory.java @@ -4,10 +4,7 @@ import com.leonardobishop.quests.Quests; import com.leonardobishop.quests.api.enums.QuestStartResult; import com.leonardobishop.quests.obj.Messages; import com.leonardobishop.quests.obj.Options; -import com.leonardobishop.quests.obj.misc.QMenu; -import com.leonardobishop.quests.obj.misc.QMenuCancel; -import com.leonardobishop.quests.obj.misc.QMenuCategory; -import com.leonardobishop.quests.obj.misc.QMenuQuest; +import com.leonardobishop.quests.obj.misc.*; import com.leonardobishop.quests.quests.Quest; import org.bukkit.Bukkit; import org.bukkit.entity.Player; @@ -90,26 +87,36 @@ public class EventInventory implements Listener { event.getWhoClicked().closeInventory(); //TODO Option to keep the menu open } } else if (event.getClick() == ClickType.MIDDLE && Options.ALLOW_QUEST_TRACK.getBooleanValue()) { - if (qMenuQuest.getOwner().getQuestProgressFile().hasStartedQuest(quest)) { - Player player = Bukkit.getPlayer(qMenuQuest.getOwner().getUuid()); - String tracked = qMenuQuest.getOwner().getQuestProgressFile().getPlayerPreferences().getTrackedQuestId(); - - if (questid.equals(tracked)) { - player.sendMessage(Messages.QUEST_TRACK_STOP.getMessage().replace("{quest}", quest.getDisplayNameStripped())); - qMenuQuest.getOwner().getQuestProgressFile().trackQuest(null); - } else { - player.sendMessage(Messages.QUEST_TRACK.getMessage().replace("{quest}", quest.getDisplayNameStripped())); - qMenuQuest.getOwner().getQuestProgressFile().trackQuest(quest); - } - event.getWhoClicked().closeInventory(); - } + middleClickQuest(qMenuQuest, quest, Bukkit.getPlayer(qMenuQuest.getOwner().getUuid())); } else if (event.getClick() == ClickType.RIGHT && Options.ALLOW_QUEST_CANCEL.getBooleanValue() && qMenuQuest.getOwner().getQuestProgressFile().hasStartedQuest(quest)) { - if (Options.QUEST_AUTOSTART.getBooleanValue()) return; - QMenuCancel qMenuCancel = new QMenuCancel(qMenuQuest.getOwner(), qMenuQuest, quest); - buffer.add(event.getWhoClicked().getUniqueId()); - event.getWhoClicked().openInventory(qMenuCancel.toInventory()); - tracker.put(event.getWhoClicked().getUniqueId(), qMenuCancel); + rightClickQuest(qMenuQuest, quest, Bukkit.getPlayer(qMenuQuest.getOwner().getUuid())); + } + } + + // **** MENU TYPE: STARTED QUESTS **** + } else if (qMenu instanceof QMenuStarted) { + QMenuStarted qMenuQuest = (QMenuStarted) qMenu; + + if (qMenuQuest.getPagePrevLocation() == event.getSlot()) { + buffer.add(event.getWhoClicked().getUniqueId()); + event.getWhoClicked().openInventory(qMenuQuest.toInventory(qMenuQuest.getCurrentPage() - 1)); + + } else if (qMenuQuest.getPageNextLocation() == event.getSlot()) { + buffer.add(event.getWhoClicked().getUniqueId()); + event.getWhoClicked().openInventory(qMenuQuest.toInventory(qMenuQuest.getCurrentPage() + 1)); + + } else if (event.getSlot() < qMenuQuest.getPageSize() && qMenuQuest.getSlotsToMenu().containsKey(event.getSlot() + (((qMenuQuest + .getCurrentPage()) - 1) * qMenuQuest.getPageSize()))) { + + // repeat from above + String questid = qMenuQuest.getSlotsToMenu().get(event.getSlot() + (((qMenuQuest.getCurrentPage()) - 1) * qMenuQuest.getPageSize())); + Quest quest = plugin.getQuestManager().getQuestById(questid); + if (event.getClick() == ClickType.MIDDLE && Options.ALLOW_QUEST_TRACK.getBooleanValue()) { + middleClickQuest(qMenuQuest, quest, Bukkit.getPlayer(qMenuQuest.getOwner().getUuid())); + } else if (event.getClick() == ClickType.RIGHT && Options.ALLOW_QUEST_CANCEL.getBooleanValue() + && qMenuQuest.getOwner().getQuestProgressFile().hasStartedQuest(quest)) { + rightClickQuest(qMenuQuest, quest, Bukkit.getPlayer(qMenuQuest.getOwner().getUuid())); } } @@ -132,10 +139,10 @@ public class EventInventory implements Listener { event.setCancelled(true); if (event.getSlot() == 10 || event.getSlot() == 11 || event.getSlot() == 12) { - QMenuQuest qMenuQuest = qMenuCancel.getSuperMenu(); + QMenu qSuperMenu = qMenuCancel.getSuperMenu(); buffer.add(event.getWhoClicked().getUniqueId()); - event.getWhoClicked().openInventory(qMenuQuest.toInventory(1)); - tracker.put(event.getWhoClicked().getUniqueId(), qMenuQuest); + event.getWhoClicked().openInventory(qSuperMenu.toInventory(1)); + tracker.put(event.getWhoClicked().getUniqueId(), qSuperMenu); } else if (event.getSlot() == 14 || event.getSlot() == 15 || event.getSlot() == 16) { if (qMenuCancel.getOwner().getQuestProgressFile().cancelQuest(qMenuCancel.getQuest())) { event.getWhoClicked().closeInventory(); @@ -145,6 +152,31 @@ public class EventInventory implements Listener { } } + private void middleClickQuest(QMenu menu, Quest quest, Player player) { + if (menu.getOwner().getQuestProgressFile().hasStartedQuest(quest)) { + String tracked = menu.getOwner().getQuestProgressFile().getPlayerPreferences().getTrackedQuestId(); + + if (quest.getId().equals(tracked)) { + player.sendMessage(Messages.QUEST_TRACK_STOP.getMessage().replace("{quest}", quest.getDisplayNameStripped())); + menu.getOwner().getQuestProgressFile().trackQuest(null); + } else { + player.sendMessage(Messages.QUEST_TRACK.getMessage().replace("{quest}", quest.getDisplayNameStripped())); + menu.getOwner().getQuestProgressFile().trackQuest(quest); + } + player.closeInventory(); + } + } + + private void rightClickQuest(QMenu menu, Quest quest, Player player) { + if (menu.getOwner().getQuestProgressFile().hasStartedQuest(quest)) { + if (Options.QUEST_AUTOSTART.getBooleanValue()) return; + QMenuCancel qMenuCancel = new QMenuCancel(menu.getOwner(), menu, quest); + buffer.add(player.getUniqueId()); + player.openInventory(qMenuCancel.toInventory(1)); + tracker.put(player.getUniqueId(), qMenuCancel); + } + } + @EventHandler public void onEvent(InventoryCloseEvent event) { // the buffer prevents players being lost from the tracker when changing menus, add to the buffer before diff --git a/src/main/java/com/leonardobishop/quests/obj/Items.java b/src/main/java/com/leonardobishop/quests/obj/Items.java index fd259bab..9725459a 100644 --- a/src/main/java/com/leonardobishop/quests/obj/Items.java +++ b/src/main/java/com/leonardobishop/quests/obj/Items.java @@ -13,6 +13,7 @@ public enum Items { PAGE_PREV("gui.page-prev"), PAGE_NEXT("gui.page-next"), PAGE_DESCRIPTION("gui.page-desc"), + NO_STARTED_QUESTS("gui.no-started-quests"), QUEST_CANCEL_YES("gui.quest-cancel-yes"), QUEST_CANCEL_NO("gui.quest-cancel-no"), QUEST_CANCEL_BACKGROUND("gui.quest-cancel-background"); diff --git a/src/main/java/com/leonardobishop/quests/obj/Options.java b/src/main/java/com/leonardobishop/quests/obj/Options.java index 409a60bf..864dde37 100644 --- a/src/main/java/com/leonardobishop/quests/obj/Options.java +++ b/src/main/java/com/leonardobishop/quests/obj/Options.java @@ -19,6 +19,7 @@ public enum Options { GUI_USE_PLACEHOLDERAPI("options.gui-use-placeholderapi"), GUITITLE_QUESTS_CATEGORY("options.guinames.quests-category"), GUITITLE_QUESTS("options.guinames.quests-menu"), + GUITITLE_QUESTS_STARTED("options.guinames.quests-started-menu"), GUITITLE_DAILY_QUESTS("options.guinames.daily-quests"), GUITITLE_QUEST_CANCEL("options.guinames.quest-cancel"), ALLOW_QUEST_CANCEL("options.allow-quest-cancel"), diff --git a/src/main/java/com/leonardobishop/quests/obj/misc/QMenu.java b/src/main/java/com/leonardobishop/quests/obj/misc/QMenu.java index 9ce5452b..a4f1bafb 100644 --- a/src/main/java/com/leonardobishop/quests/obj/misc/QMenu.java +++ b/src/main/java/com/leonardobishop/quests/obj/misc/QMenu.java @@ -1,6 +1,7 @@ package com.leonardobishop.quests.obj.misc; import com.leonardobishop.quests.player.QPlayer; +import org.bukkit.inventory.Inventory; import java.util.HashMap; @@ -8,5 +9,6 @@ public interface QMenu { QPlayer getOwner(); HashMap getSlotsToMenu(); + Inventory toInventory(int page); } diff --git a/src/main/java/com/leonardobishop/quests/obj/misc/QMenuCancel.java b/src/main/java/com/leonardobishop/quests/obj/misc/QMenuCancel.java index 72445aaf..1c04d5cc 100644 --- a/src/main/java/com/leonardobishop/quests/obj/misc/QMenuCancel.java +++ b/src/main/java/com/leonardobishop/quests/obj/misc/QMenuCancel.java @@ -17,11 +17,11 @@ import java.util.Map; public class QMenuCancel implements QMenu { private final HashMap slotsToQuestIds = new HashMap<>(); - private final QMenuQuest superMenu; + private final QMenu superMenu; private final QPlayer owner; private final Quest quest; - public QMenuCancel(QPlayer owner, QMenuQuest superMenu, Quest quest) { + public QMenuCancel(QPlayer owner, QMenu superMenu, Quest quest) { this.owner = owner; this.superMenu = superMenu; this.quest = quest; @@ -45,7 +45,7 @@ public class QMenuCancel implements QMenu { return owner; } - public Inventory toInventory() { + public Inventory toInventory(int page) { String title = Options.color(Options.GUITITLE_QUEST_CANCEL.getStringValue()); ItemStack yes = Items.QUEST_CANCEL_YES.getItem(); @@ -73,7 +73,7 @@ public class QMenuCancel implements QMenu { return inventory; } - public QMenuQuest getSuperMenu() { + public QMenu getSuperMenu() { return superMenu; } diff --git a/src/main/java/com/leonardobishop/quests/obj/misc/QMenuStarted.java b/src/main/java/com/leonardobishop/quests/obj/misc/QMenuStarted.java new file mode 100644 index 00000000..88222b57 --- /dev/null +++ b/src/main/java/com/leonardobishop/quests/obj/misc/QMenuStarted.java @@ -0,0 +1,176 @@ +package com.leonardobishop.quests.obj.misc; + +import com.leonardobishop.quests.Quests; +import com.leonardobishop.quests.obj.Items; +import com.leonardobishop.quests.obj.Options; +import com.leonardobishop.quests.player.QPlayer; +import com.leonardobishop.quests.player.questprogressfile.QuestProgress; +import com.leonardobishop.quests.quests.Quest; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; + +import java.util.*; + +public class QMenuStarted implements QMenu { + + private final Quests plugin; + private final HashMap slotsToQuestIds = new HashMap<>(); + private final int pageSize = 45; + private final QPlayer owner; + + private int pagePrevLocation = -1; + private int pageNextLocation = -1; + private int currentPage = -1; + + public QMenuStarted(Quests plugin, QPlayer owner) { + this.plugin = plugin; + this.owner = owner; + } + + public void populate(List quests) { + Collections.sort(quests); + int slot = 0; + for (QuestSortWrapper quest : quests) { + if (owner.getQuestProgressFile().hasStartedQuest(quest.getQuest())) { + slotsToQuestIds.put(slot, quest.getQuest().getId()); + slot++; + } + } + } + + @Override + public HashMap getSlotsToMenu() { + return slotsToQuestIds; + } + + @Override + public QPlayer getOwner() { + return owner; + } + + public int getPagePrevLocation() { + return pagePrevLocation; + } + + public int getPageNextLocation() { + return pageNextLocation; + } + + public int getCurrentPage() { + return currentPage; + } + + public int getPageSize() { + return pageSize; + } + + public Inventory toInventory(int page) { + currentPage = page; + int pageMin = pageSize * (page - 1); + int pageMax = pageSize * page; + String title = Options.color(Options.GUITITLE_QUESTS_STARTED.getStringValue()); + + ItemStack pageIs; + ItemStack pagePrevIs; + ItemStack pageNextIs; + ItemStack none = Items.NO_STARTED_QUESTS.getItem(); + + Inventory inventory = Bukkit.createInventory(null, 54, title); + + int invSlot = 0; + if (!slotsToQuestIds.isEmpty()) { + for (int pointer = pageMin; pointer < pageMax; pointer++) { + if (slotsToQuestIds.containsKey(pointer)) { + Quest quest = Quests.get().getQuestManager().getQuestById(slotsToQuestIds.get(pointer)); + QuestProgress questProgress = owner.getQuestProgressFile().getQuestProgress(quest); + + inventory.setItem(invSlot, replaceItemStack(Quests.get().getQuestManager().getQuestById( + quest.getId()).getDisplayItem().toItemStack(quest, owner.getQuestProgressFile(), questProgress))); + } + invSlot++; + } + } else { + inventory.setItem(4, none); + } + + pageNextLocation = -1; + pagePrevLocation = -1; + + Map pageplaceholders = new HashMap<>(); + pageplaceholders.put("{prevpage}", String.valueOf(page - 1)); + pageplaceholders.put("{nextpage}", String.valueOf(page + 1)); + pageplaceholders.put("{page}", String.valueOf(page)); + pageIs = replaceItemStack(Items.PAGE_DESCRIPTION.getItem(), pageplaceholders); + pagePrevIs = replaceItemStack(Items.PAGE_PREV.getItem(), pageplaceholders); + pageNextIs = replaceItemStack(Items.PAGE_NEXT.getItem(), pageplaceholders); + + if (slotsToQuestIds.size() > pageSize) { + inventory.setItem(49, pageIs); + if (page != 1) { + inventory.setItem(48, pagePrevIs); + pagePrevLocation = 48; + } + if (Math.ceil((double) slotsToQuestIds.size() / ((double) 45)) != page) { + inventory.setItem(50, pageNextIs); + pageNextLocation = 50; + } + } else if (Options.TRIM_GUI_SIZE.getBooleanValue() && page == 1) { + int slotsUsed = 0; + for (int pointer = 0; pointer < pageMax; pointer++) { + if (inventory.getItem(pointer) != null) { + slotsUsed++; + } + } + + int inventorySize = (slotsUsed >= 54) ? 54 : slotsUsed + (9 - slotsUsed % 9) * Math.min(1, slotsUsed % 9); + inventorySize = inventorySize <= 0 ? 9 : inventorySize; + if (inventorySize == 54) { + return inventory; + } + + Inventory trimmedInventory = Bukkit.createInventory(null, inventorySize, title); + + for (int slot = 0; slot < trimmedInventory.getSize(); slot++) { + trimmedInventory.setItem(slot, inventory.getItem(slot)); + } + return trimmedInventory; + } + + return inventory; + } + + public ItemStack replaceItemStack(ItemStack is) { + return replaceItemStack(is, Collections.emptyMap()); + } + + public ItemStack replaceItemStack(ItemStack is, Map placeholders) { + ItemStack newItemStack = is.clone(); + List lore = newItemStack.getItemMeta().getLore(); + List newLore = new ArrayList<>(); + ItemMeta ism = newItemStack.getItemMeta(); + Player player = Bukkit.getPlayer(owner.getUuid()); + if (lore != null) { + for (String s : lore) { + for (Map.Entry entry : placeholders.entrySet()) { + s = s.replace(entry.getKey(), entry.getValue()); + if (plugin.getPlaceholderAPIHook() != null && Options.GUI_USE_PLACEHOLDERAPI.getBooleanValue()) { + s = plugin.getPlaceholderAPIHook().replacePlaceholders(player, s); + } + } + newLore.add(s); + } + } + for (Map.Entry entry : placeholders.entrySet()) { + ism.setDisplayName(ism.getDisplayName().replace(entry.getKey(), entry.getValue())); + if (plugin.getPlaceholderAPIHook() != null && Options.GUI_USE_PLACEHOLDERAPI.getBooleanValue()) { + ism.setDisplayName(plugin.getPlaceholderAPIHook().replacePlaceholders(player, ism.getDisplayName())); + } + } + ism.setLore(newLore); + newItemStack.setItemMeta(ism); + return newItemStack; + } +} diff --git a/src/main/java/com/leonardobishop/quests/obj/misc/QuestSortWrapper.java b/src/main/java/com/leonardobishop/quests/obj/misc/QuestSortWrapper.java new file mode 100644 index 00000000..40cd563d --- /dev/null +++ b/src/main/java/com/leonardobishop/quests/obj/misc/QuestSortWrapper.java @@ -0,0 +1,44 @@ +package com.leonardobishop.quests.obj.misc; + +import com.leonardobishop.quests.Quests; +import com.leonardobishop.quests.quests.Category; +import com.leonardobishop.quests.quests.Quest; + +public class QuestSortWrapper implements Comparable { + + private int weightedSortOrder; + private final Quest quest; + + public QuestSortWrapper(Quests plugin, Quest quest) { + this.quest = quest; + if (quest.getCategoryId() == null) { + weightedSortOrder = quest.getSortOrder(); + return; + } + Category c = plugin.getQuestManager().getCategoryById(quest.getCategoryId()); + if (c != null) { + int index = plugin.getQuestManager().getCategories().indexOf(c); + int amountBelow = 0; + //TODO precalculate + for (int i = index; i > 0; i--) { + Category below = plugin.getQuestManager().getCategories().get(i - 1); + amountBelow += below.getRegisteredQuestIds().size(); + } + weightedSortOrder = amountBelow + quest.getSortOrder(); + } + } + + public int getWeightedSortOrder() { + return weightedSortOrder; + } + + public Quest getQuest() { + return quest; + } + + @Override + public int compareTo(QuestSortWrapper quest) { + return (weightedSortOrder - quest.weightedSortOrder); + } + +} diff --git a/src/main/java/com/leonardobishop/quests/player/QPlayer.java b/src/main/java/com/leonardobishop/quests/player/QPlayer.java index 6c270fa1..45d58012 100644 --- a/src/main/java/com/leonardobishop/quests/player/QPlayer.java +++ b/src/main/java/com/leonardobishop/quests/player/QPlayer.java @@ -5,6 +5,8 @@ import com.leonardobishop.quests.events.EventInventory; import com.leonardobishop.quests.obj.Options; import com.leonardobishop.quests.obj.misc.QMenuCategory; import com.leonardobishop.quests.obj.misc.QMenuQuest; +import com.leonardobishop.quests.obj.misc.QMenuStarted; +import com.leonardobishop.quests.obj.misc.QuestSortWrapper; import com.leonardobishop.quests.player.questprogressfile.QuestProgressFile; import com.leonardobishop.quests.quests.Category; import com.leonardobishop.quests.quests.Quest; @@ -22,7 +24,7 @@ public class QPlayer { private final QuestProgressFile questProgressFile; private final Quests plugin; - public QPlayer(UUID uuid, QuestProgressFile questProgressFile, Quests plugin) { + public QPlayer(UUID uuid, QuestProgressFile questProgressFile, Quests plugin) { this.uuid = uuid; this.questProgressFile = questProgressFile; this.plugin = plugin; @@ -119,6 +121,26 @@ public class QPlayer { } } + public void openStartedQuests() { + if (this.uuid == null) { + return; + } + Player player = Bukkit.getPlayer(this.uuid); + if (player == null) { + return; + } + + QMenuStarted qMenuStarted = new QMenuStarted(plugin, plugin.getPlayerManager().getPlayer(player.getUniqueId())); + List quests = new ArrayList<>(); + for (Map.Entry entry : plugin.getQuestManager().getQuests().entrySet()) { + quests.add(new QuestSortWrapper(plugin, entry.getValue())); + } + qMenuStarted.populate(quests); + + player.openInventory(qMenuStarted.toInventory(1)); + EventInventory.track(player.getUniqueId(), qMenuStarted); + } + public QuestProgressFile getQuestProgressFile() { return questProgressFile; } diff --git a/src/main/java/com/leonardobishop/quests/quests/Quest.java b/src/main/java/com/leonardobishop/quests/quests/Quest.java index 8c02a6c4..76aaefcf 100644 --- a/src/main/java/com/leonardobishop/quests/quests/Quest.java +++ b/src/main/java/com/leonardobishop/quests/quests/Quest.java @@ -118,6 +118,10 @@ public class Quest implements Comparable { return placeholders; } + public int getSortOrder() { + return sortOrder; + } + @Override public int compareTo(Quest quest) { return (sortOrder - quest.sortOrder); diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 4dffe279..ce523a3b 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -111,6 +111,11 @@ gui: - "&7(&a{quest}&7) and cannot." - "&7repeat it." type: "GREEN_STAINED_GLASS_PANE" + no-started-quests: + name: "&c&lNo Started Quests" + lore: + - "&7You have not started any quests." + type: "FEATHER" quest-cancel-yes: name: "&a&lConfirm Cancel" lore: @@ -145,6 +150,7 @@ options: guinames: quests-category: "Quests Categories" quests-menu: "Quests" + quests-started-menu: "Started Quests" daily-quests: "Daily Quests" quest-cancel: "Cancel Quest" # Show when quests register in console - will only show if verbose-logging-level=2. Disable if you want less console spam at startup. -- cgit v1.2.3-70-g09d2