From 5a26883b70d65a08108902d28cd2c84ef5ccc7ab Mon Sep 17 00:00:00 2001 From: Krakenied Date: Sun, 20 Jul 2025 19:13:57 +0200 Subject: Add item option to dealdamage Closes https://github.com/LMBishop/Quests/issues/735 --- .../bukkit/tasktype/type/DealDamageTaskType.java | 36 ++++++++++++++++++++++ docs/task-types/dealdamage-(task-type).md | 18 +++++++---- 2 files changed, 48 insertions(+), 6 deletions(-) diff --git a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/tasktype/type/DealDamageTaskType.java b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/tasktype/type/DealDamageTaskType.java index 2f4bb902..1be17aa0 100644 --- a/bukkit/src/main/java/com/leonardobishop/quests/bukkit/tasktype/type/DealDamageTaskType.java +++ b/bukkit/src/main/java/com/leonardobishop/quests/bukkit/tasktype/type/DealDamageTaskType.java @@ -1,6 +1,9 @@ package com.leonardobishop.quests.bukkit.tasktype.type; +import com.google.common.collect.HashBasedTable; +import com.google.common.collect.Table; import com.leonardobishop.quests.bukkit.BukkitQuestsPlugin; +import com.leonardobishop.quests.bukkit.item.QuestItem; import com.leonardobishop.quests.bukkit.tasktype.BukkitTaskType; import com.leonardobishop.quests.bukkit.util.TaskUtils; import com.leonardobishop.quests.bukkit.util.constraint.TaskConstraintSet; @@ -16,11 +19,13 @@ import org.bukkit.entity.Projectile; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.entity.EntityDamageByEntityEvent; +import org.bukkit.inventory.ItemStack; import org.bukkit.projectiles.ProjectileSource; public final class DealDamageTaskType extends BukkitTaskType { private final BukkitQuestsPlugin plugin; + private final Table fixedQuestItemCache = HashBasedTable.create(); public DealDamageTaskType(BukkitQuestsPlugin plugin) { super("dealdamage", TaskUtils.TASK_ATTRIBUTION_STRING, "Deal a certain amount of damage."); @@ -30,15 +35,22 @@ public final class DealDamageTaskType extends BukkitTaskType { super.addConfigValidator(TaskUtils.useIntegerConfigValidator(this, "amount")); super.addConfigValidator(TaskUtils.useEntityListConfigValidator(this, "mob", "mobs")); super.addConfigValidator(TaskUtils.useBooleanConfigValidator(this, "allow-only-creatures")); + super.addConfigValidator(TaskUtils.useItemStackConfigValidator(this, "item")); + super.addConfigValidator(TaskUtils.useIntegerConfigValidator(this, "data")); + super.addConfigValidator(TaskUtils.useBooleanConfigValidator(this, "exact-match")); } @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onEntityDamageByEntity(EntityDamageByEntityEvent event) { Entity damager = event.getDamager(); + ItemStack weapon = null; Player player; if (damager instanceof Player) { player = (Player) damager; + + // It can be set there, but unfortunately we are unable to handle bows properly + weapon = player.getInventory().getItemInMainHand(); } else if (damager instanceof Projectile projectile) { ProjectileSource source = projectile.getShooter(); @@ -90,6 +102,30 @@ public final class DealDamageTaskType extends BukkitTaskType { continue; } + if (task.hasConfigKey("item")) { + if (weapon == null) { + super.debug("Specific item is required, player has no item in hand; continuing...", quest.getId(), task.getId(), player.getUniqueId()); + continue; + } + + super.debug("Specific item is required; player held item is of type '" + weapon.getType() + "'", quest.getId(), task.getId(), player.getUniqueId()); + + QuestItem qi; + if ((qi = fixedQuestItemCache.get(quest.getId(), task.getId())) == null) { + QuestItem fetchedItem = TaskUtils.getConfigQuestItem(task, "item", "data"); + fixedQuestItemCache.put(quest.getId(), task.getId(), fetchedItem); + qi = fetchedItem; + } + + boolean exactMatch = TaskUtils.getConfigBoolean(task, "exact-match", true); + if (!qi.compareItemStack(weapon, exactMatch)) { + super.debug("Item does not match required item, continuing...", quest.getId(), task.getId(), player.getUniqueId()); + continue; + } else { + super.debug("Item matches required item", quest.getId(), task.getId(), player.getUniqueId()); + } + } + int amount = (int) task.getConfigValue("amount"); double progress = Math.min(amount, TaskUtils.getDecimalTaskProgress(taskProgress) + damage); diff --git a/docs/task-types/dealdamage-(task-type).md b/docs/task-types/dealdamage-(task-type).md index 30d19b47..d485b4f1 100644 --- a/docs/task-types/dealdamage-(task-type).md +++ b/docs/task-types/dealdamage-(task-type).md @@ -13,12 +13,18 @@ Deal a certain amount of damage. ## Options -| Key | Description | Type | Required | Default | Notes | -|------------------------|-------------------------------------------------|--------------------------------------|----------|---------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `amount` | The amount of damage needed. | Integer | Yes | \- | Damage is measured in HP, 1 heart = 2 HP. A player has 20 HP by default, with no status effects applied. | -| `allow-only-creatures` | Whether the entity must be a creature. | Boolean | No | True | \- | -| `mob` / `mobs` | The specific mob(s) to kill. | Entity type, or list of entity types | No | \- | Not specifying this field will allow all mob types to count towards the task. Please see [this list](https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/entity/EntityType.html) for entity types. | -| `worlds` | Worlds which should count towards the progress. | List of world names | No | \- | \- | +| Key | Description | Type | Required | Default | Notes | +|------------------------|--------------------------------------------------------|--------------------------------------|----------|---------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `amount` | The amount of damage needed. | Integer | Yes | \- | Damage is measured in HP, 1 heart = 2 HP. A player has 20 HP by default, with no status effects applied. | +| `allow-only-creatures` | Whether the entity must be a creature. | Boolean | No | True | \- | +| `mob` / `mobs` | The specific mob(s) to deal damage to. | Entity type, or list of entity types | No | \- | Not specifying this field will allow all mob types to count towards the task. Please see [this list](https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/entity/EntityType.html) for entity types. | +| `item` | Specific item which should be used to deal damage. | ItemStack | No | \- | Accepts standard [item definition](../configuration/defining-items). | +| `data` | The data code for the item. | Integer | No | 0 | This field is not used in Minecraft versions 1.13+, nor is it compatible with ItemStack definitions. | +| `exact-match` | Whether the item should exactly match what is defined. | Boolean | No | true | \- | +| `worlds` | Worlds which should count towards the progress. | List of world names | No | \- | \- | + +{: .caution } +It's not possible to use item option for projectile weapons (like bow or other projectile shooters). Currently, the API is insufficient to implement such a feature without any unwanted side effects. ## Examples -- cgit v1.2.3-70-g09d2