mirror of
https://gitlab.com/phoenix-dvpmt/mmoitems.git
synced 2025-03-11 13:11:50 +01:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
0b27f8ca55
4
pom.xml
4
pom.xml
@ -4,7 +4,7 @@
|
|||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>net.Indyuce</groupId>
|
<groupId>net.Indyuce</groupId>
|
||||||
<artifactId>MMOItems</artifactId>
|
<artifactId>MMOItems</artifactId>
|
||||||
<version>6.7-SNAPSHOT</version>
|
<version>6.7.1-SNAPSHOT</version>
|
||||||
<name>MMOItems</name>
|
<name>MMOItems</name>
|
||||||
<description>A great item solution for your RPG server!!</description>
|
<description>A great item solution for your RPG server!!</description>
|
||||||
|
|
||||||
@ -141,7 +141,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.lumine</groupId>
|
<groupId>io.lumine</groupId>
|
||||||
<artifactId>MythicLib-dist</artifactId>
|
<artifactId>MythicLib-dist</artifactId>
|
||||||
<version>1.3-R22-SNAPSHOT</version>
|
<version>1.3-R25-SNAPSHOT</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
@ -96,7 +96,7 @@ public class MMOItems extends LuminePlugin {
|
|||||||
private VaultSupport vaultSupport;
|
private VaultSupport vaultSupport;
|
||||||
private RPGHandler rpgPlugin;
|
private RPGHandler rpgPlugin;
|
||||||
|
|
||||||
private static final int MYTHICLIB_COMPATIBILITY_INDEX = 5;
|
private static final int MYTHICLIB_COMPATIBILITY_INDEX = 6;
|
||||||
|
|
||||||
public MMOItems() { plugin = this; }
|
public MMOItems() { plugin = this; }
|
||||||
|
|
||||||
@ -800,6 +800,17 @@ public class MMOItems extends LuminePlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JULES DO NOT DELETE THIS AGAIN I KNOW ITS UNUSED PRECISELY BECAUSE I ALWAYS COMMENT
|
||||||
|
* ALL ITS USAGES BEFORE PUSHING ANY UPDATES, I USE IT FOR SPAMMY DEVELOPER MESSAGES
|
||||||
|
*
|
||||||
|
* Note that {@link #print(Level, String, String, String...)} is used for actual warnings
|
||||||
|
* or such that the users may see, so dont delete that one either.
|
||||||
|
*
|
||||||
|
* @author Gunging
|
||||||
|
*/
|
||||||
|
public static void log(@Nullable String message, @NotNull String... replaces) { print(null, message, null, replaces); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The server's console sender.
|
* @return The server's console sender.
|
||||||
* @author Gunging
|
* @author Gunging
|
||||||
|
@ -59,7 +59,10 @@ public class MMOUtils {
|
|||||||
switch (name) {
|
switch (name) {
|
||||||
case "ON_HIT": return TriggerType.ATTACK;
|
case "ON_HIT": return TriggerType.ATTACK;
|
||||||
case "WHEN_HIT": return TriggerType.DAMAGED;
|
case "WHEN_HIT": return TriggerType.DAMAGED;
|
||||||
default: return TriggerType.valueOf(name);
|
default:
|
||||||
|
|
||||||
|
TriggerType trigger = TriggerType.valueOf(name);
|
||||||
|
return trigger;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,9 @@ import net.Indyuce.mmoitems.api.item.template.MMOItemTemplate;
|
|||||||
import net.Indyuce.mmoitems.api.player.RPGPlayer;
|
import net.Indyuce.mmoitems.api.player.RPGPlayer;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Consider using {@link MMOItemUIFilter}, stores the same information but works more abstractly from MythicLib.
|
||||||
|
*/
|
||||||
public class ConfigMMOItem {
|
public class ConfigMMOItem {
|
||||||
private final MMOItemTemplate template;
|
private final MMOItemTemplate template;
|
||||||
private final int amount;
|
private final int amount;
|
||||||
@ -58,7 +61,5 @@ public class ConfigMMOItem {
|
|||||||
return preview == null ? (preview = template.newBuilder(0, null).build().newBuilder().build(true)).clone() : preview.clone();
|
return preview == null ? (preview = template.newBuilder(0, null).build().newBuilder().build(true)).clone() : preview.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getAmount() {
|
public int getAmount() { return amount; }
|
||||||
return amount;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -151,7 +151,7 @@ public class CraftingStation extends PostLoadObject {
|
|||||||
* parameter because old files would be out of date, instead just looks for
|
* parameter because old files would be out of date, instead just looks for
|
||||||
* a parameter of the crafting recipe which is 'output'
|
* a parameter of the crafting recipe which is 'output'
|
||||||
*/
|
*/
|
||||||
private Recipe loadRecipe(ConfigurationSection config) {
|
private Recipe loadRecipe(ConfigurationSection config) throws IllegalArgumentException {
|
||||||
return config.contains("output") ? new CraftingRecipe(config) : new UpgradingRecipe(config);
|
return config.contains("output") ? new CraftingRecipe(config) : new UpgradingRecipe(config);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
*/
|
*/
|
||||||
public abstract class Ingredient<C extends PlayerIngredient> {
|
public abstract class Ingredient<C extends PlayerIngredient> {
|
||||||
private final String id;
|
private final String id;
|
||||||
private final int amount;
|
private int amount;
|
||||||
|
|
||||||
public Ingredient(String id, MMOLineConfig config) {
|
public Ingredient(String id, MMOLineConfig config) {
|
||||||
this(id, config.getInt("amount", 1));
|
this(id, config.getInt("amount", 1));
|
||||||
@ -35,6 +35,7 @@ public abstract class Ingredient<C extends PlayerIngredient> {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setAmount(int amount) { this.amount = amount; }
|
||||||
public int getAmount() {
|
public int getAmount() {
|
||||||
return amount;
|
return amount;
|
||||||
}
|
}
|
||||||
|
@ -22,8 +22,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
public class MMOItemIngredient extends Ingredient<MMOItemPlayerIngredient> {
|
public class MMOItemIngredient extends Ingredient<MMOItemPlayerIngredient> {
|
||||||
private final MMOItemTemplate template;
|
private final MMOItemTemplate template;
|
||||||
|
|
||||||
@NotNull
|
@NotNull private final QuickNumberRange level;
|
||||||
private final QuickNumberRange level;
|
|
||||||
private final String display;
|
private final String display;
|
||||||
|
|
||||||
public MMOItemIngredient(MMOLineConfig config) {
|
public MMOItemIngredient(MMOLineConfig config) {
|
||||||
|
@ -1,63 +1,164 @@
|
|||||||
package net.Indyuce.mmoitems.api.crafting.ingredient;
|
package net.Indyuce.mmoitems.api.crafting.ingredient;
|
||||||
|
|
||||||
import io.lumine.mythic.lib.api.MMOLineConfig;
|
import io.lumine.mythic.lib.api.MMOLineConfig;
|
||||||
|
import io.lumine.mythic.lib.api.crafting.uifilters.VanillaUIFilter;
|
||||||
|
import io.lumine.mythic.lib.api.crafting.uimanager.ProvidedUIFilter;
|
||||||
|
import io.lumine.mythic.lib.api.crafting.uimanager.UIFilterManager;
|
||||||
import io.lumine.mythic.lib.api.item.NBTItem;
|
import io.lumine.mythic.lib.api.item.NBTItem;
|
||||||
import io.lumine.mythic.lib.api.util.LegacyComponent;
|
import io.lumine.mythic.lib.api.util.LegacyComponent;
|
||||||
|
import io.lumine.mythic.lib.api.util.ui.FriendlyFeedbackCategory;
|
||||||
|
import io.lumine.mythic.lib.api.util.ui.FriendlyFeedbackMessage;
|
||||||
|
import io.lumine.mythic.lib.api.util.ui.FriendlyFeedbackProvider;
|
||||||
|
import io.lumine.mythic.lib.api.util.ui.SilentNumbers;
|
||||||
|
import net.Indyuce.mmoitems.MMOItems;
|
||||||
import net.Indyuce.mmoitems.MMOUtils;
|
import net.Indyuce.mmoitems.MMOUtils;
|
||||||
import net.Indyuce.mmoitems.api.crafting.ingredient.inventory.VanillaPlayerIngredient;
|
import net.Indyuce.mmoitems.api.crafting.ingredient.inventory.VanillaPlayerIngredient;
|
||||||
import net.Indyuce.mmoitems.api.player.RPGPlayer;
|
import net.Indyuce.mmoitems.api.player.RPGPlayer;
|
||||||
|
import net.Indyuce.mmoitems.api.util.message.FFPMMOItems;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
public class VanillaIngredient extends Ingredient<VanillaPlayerIngredient> {
|
public class VanillaIngredient extends Ingredient<VanillaPlayerIngredient> {
|
||||||
private final Material material;
|
@NotNull public ProvidedUIFilter getFilter() { return filter; }
|
||||||
|
@NotNull final ProvidedUIFilter filter;
|
||||||
|
|
||||||
|
@NotNull public Material getMaterial() { return material; }
|
||||||
|
@NotNull final Material material;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* displayName is the itemMeta display name; display corresponds to how the
|
* displayName is the itemMeta display name; display corresponds to how the
|
||||||
* ingredient displays in the crafting recipe GUI item lore
|
* ingredient displays in the crafting recipe GUI item lore
|
||||||
*/
|
*/
|
||||||
private final String displayName, display;
|
@NotNull final String display;
|
||||||
|
@Nullable final String displayName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use vanilla stuff?
|
||||||
|
*/
|
||||||
|
boolean vanillaBackward = true;
|
||||||
|
|
||||||
public VanillaIngredient(MMOLineConfig config) {
|
public VanillaIngredient(MMOLineConfig config) {
|
||||||
super("vanilla", config);
|
super("vanilla", config);
|
||||||
|
|
||||||
config.validate("type");
|
FriendlyFeedbackProvider ffp = new FriendlyFeedbackProvider(FFPMMOItems.get());
|
||||||
|
|
||||||
material = Material.valueOf(config.getString("type").toUpperCase().replace("-", "_").replace(" ", "_"));
|
// Validate type I guess
|
||||||
|
config.validate("type");
|
||||||
|
String itemFilter = config.getString("type", "");
|
||||||
|
|
||||||
|
//VING//MMOItems.log("\u00a78VING\u00a73 RD\u00a77 Reading\u00a7a " + itemFilter);
|
||||||
|
|
||||||
|
// UIFilter or Vanilla Backwards Compatible?
|
||||||
|
if (itemFilter.contains(" ")) {
|
||||||
|
vanillaBackward = false;
|
||||||
|
//VING//MMOItems.log("\u00a78VING\u00a73 RD\u00a77 As Item Filter (yes)");
|
||||||
|
|
||||||
|
// Which item
|
||||||
|
ProvidedUIFilter sweetFilter = UIFilterManager.getUIFilter(itemFilter, ffp);
|
||||||
|
if (sweetFilter == null) {
|
||||||
|
|
||||||
|
// Throw message
|
||||||
|
throw new IllegalArgumentException(SilentNumbers.collapseList(SilentNumbers.transcribeList(ffp.getFeedbackOf(FriendlyFeedbackCategory.ERROR), message -> { if (message instanceof FriendlyFeedbackMessage) { return ((FriendlyFeedbackMessage) message).forConsole(FFPMMOItems.get()); } return ""; }), ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accepted as not-null
|
||||||
|
filter = sweetFilter;
|
||||||
|
|
||||||
|
// Valid UIFilter?
|
||||||
|
if (!filter.isValid(ffp)) {
|
||||||
|
|
||||||
|
// Throw message
|
||||||
|
throw new IllegalArgumentException(SilentNumbers.collapseList(SilentNumbers.transcribeList(ffp.getFeedbackOf(FriendlyFeedbackCategory.ERROR), message -> { if (message instanceof FriendlyFeedbackMessage) { return ((FriendlyFeedbackMessage) message).forConsole(FFPMMOItems.get()); } return ""; }), ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Consistent amounts
|
||||||
|
setAmount(filter.getAmount(getAmount()));
|
||||||
|
filter.setAmount(getAmount());
|
||||||
|
|
||||||
|
// Find the display name of the item
|
||||||
|
display = config.getString("display", findName());
|
||||||
|
material = Material.STONE;
|
||||||
|
//VING//MMOItems.log("\u00a78VING\u00a73 RD\u00a77 Determined\u00a7e " + filter);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
//VING//MMOItems.log("\u00a78VING\u00a73 RD\u00a77 As Material (eh)");
|
||||||
|
|
||||||
|
// Parse material
|
||||||
|
material = Material.valueOf(itemFilter.toUpperCase().replace("-", "_").replace(" ", "_"));
|
||||||
|
|
||||||
|
// Filter
|
||||||
|
filter = new ProvidedUIFilter(VanillaUIFilter.get(), material.toString(), "0");
|
||||||
|
filter.setAmount(getAmount());
|
||||||
|
|
||||||
|
// Display is the name of the material, or whatever specified in the config.
|
||||||
|
display = config.getString("display", MMOUtils.caseOnWords(material.toString().toLowerCase().replace("_", " ")));
|
||||||
|
//VING//MMOItems.log("\u00a78VING\u00a73 RD\u00a77 Determined\u00a73 " + material.toString());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Valid UIFilter?
|
||||||
|
if (filter.getItemStack(null) == null) {
|
||||||
|
|
||||||
|
// Throw message
|
||||||
|
throw new IllegalArgumentException(SilentNumbers.collapseList(SilentNumbers.transcribeList(ffp.getFeedbackOf(FriendlyFeedbackCategory.ERROR), message -> { if (message instanceof FriendlyFeedbackMessage) { return ((FriendlyFeedbackMessage) message).forConsole(FFPMMOItems.get()); } return ""; }), ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display-Name, apparently
|
||||||
displayName = config.contains("name") ? config.getString("name") : null;
|
displayName = config.contains("name") ? config.getString("name") : null;
|
||||||
|
|
||||||
display = config.contains("display") ? config.getString("display") : MMOUtils.caseOnWords(material.name().toLowerCase().replace("_", " "));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override public String getKey() { return "vanilla:" + (vanillaBackward ? material.toString().toLowerCase() : filter.toString().toLowerCase().replace(" ", "__")) + "_" + displayName; }
|
||||||
public String getKey() {
|
|
||||||
return "vanilla:" + material.name().toLowerCase() + "_" + displayName;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override public String formatDisplay(String s) { return s.replace("#item#", display).replace("#amount#", String.valueOf(getAmount())); }
|
||||||
public String formatDisplay(String s) {
|
|
||||||
return s.replace("#item#", display).replace("#amount#", "" + getAmount());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean matches(VanillaPlayerIngredient ing) {
|
public boolean matches(VanillaPlayerIngredient ing) {
|
||||||
|
//VING//MMOItems.log("\u00a78VING\u00a79 MCH\u00a77 Comparing given \u00a73 " + SilentNumbers.getItemName(ing.getSourceItem()) + " to expected\u00a79 " + filter);
|
||||||
|
|
||||||
// Check for material
|
if (vanillaBackward) {
|
||||||
if (ing.getType() != material)
|
// Check for material
|
||||||
return false;
|
if (ing.getType() != material) {
|
||||||
|
//VING//MMOItems.log("\u00a78VING\u00a79 MCH\u00a7c Not right material \u00a78(expected \u00a76" + material.toString() + "\u00a78)");
|
||||||
|
return false; }
|
||||||
|
|
||||||
// Check for display name
|
//MMOItems.log("\u00a78VING\u00a79 MCH\u00a77 Display Name Ingredient:\u00a7a " + ing.getDisplayName());
|
||||||
return ing.getDisplayName() != null ? ing.getDisplayName().equals(displayName) : displayName == null;
|
//MMOItems.log("\u00a78VING\u00a79 MCH\u00a77 Display Name Requested:\u00a7a " + displayName);
|
||||||
|
//MMOItems.log("\u00a78VING\u00a79 MCH\u00a77 Display Name Check:\u00a7a " + (ing.getDisplayName() != null ? ing.getDisplayName().equals(displayName) : displayName == null));
|
||||||
|
|
||||||
|
// Check for display name
|
||||||
|
return ing.getDisplayName() != null ? ing.getDisplayName().equals(displayName) : displayName == null;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
//VING//MMOItems.log("\u00a78VING\u00a79 MCH\u00a77 Poof Check \u00a73 " + filter + "\u00a77: \u00a7a " + (filter.matches(ing.getSourceItem(), true, null)));
|
||||||
|
|
||||||
|
// Sweet PooF matching
|
||||||
|
return filter.matches(ing.getSourceItem(), true, null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public ItemStack generateItemStack(@NotNull RPGPlayer player) {
|
public ItemStack generateItemStack(@NotNull RPGPlayer player) {
|
||||||
NBTItem item = NBTItem.get(new ItemStack(material, getAmount()));
|
|
||||||
if (displayName != null) {
|
// Stack
|
||||||
item.setDisplayNameComponent(LegacyComponent.parse(displayName));
|
ItemStack stack = filter.getItemStack(null);
|
||||||
}
|
stack.setAmount(getAmount());
|
||||||
|
|
||||||
|
// Apparently get as NBT Item
|
||||||
|
NBTItem item = NBTItem.get(stack);
|
||||||
|
|
||||||
|
// Then rename (okay)
|
||||||
|
if (displayName != null) { item.setDisplayNameComponent(LegacyComponent.parse(displayName)); }
|
||||||
|
|
||||||
|
// Return
|
||||||
return item.toItem();
|
return item.toItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The name of the item the ProvidedUIFilter encodes for.
|
||||||
|
*/
|
||||||
|
@NotNull String findName() { return SilentNumbers.getItemName(filter.getParent().getDisplayStack(filter.getArgument(), filter.getData(), null), false); }
|
||||||
}
|
}
|
||||||
|
@ -2,22 +2,28 @@ package net.Indyuce.mmoitems.api.crafting.ingredient.inventory;
|
|||||||
|
|
||||||
import io.lumine.mythic.lib.api.item.NBTItem;
|
import io.lumine.mythic.lib.api.item.NBTItem;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.inventory.meta.ItemMeta;
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
public class VanillaPlayerIngredient extends PlayerIngredient {
|
public class VanillaPlayerIngredient extends PlayerIngredient {
|
||||||
|
@NotNull public ItemStack getSourceItem() { return sourceItem; }
|
||||||
|
@NotNull final ItemStack sourceItem;
|
||||||
|
|
||||||
private final Material material;
|
private final Material material;
|
||||||
@Nullable
|
@Nullable private final String displayName;
|
||||||
private final String displayName;
|
|
||||||
|
|
||||||
public VanillaPlayerIngredient(NBTItem item) {
|
public VanillaPlayerIngredient(NBTItem item) {
|
||||||
super(item);
|
super(item);
|
||||||
|
|
||||||
|
// Restore item
|
||||||
|
sourceItem = item.toItem();
|
||||||
this.material = item.getItem().getType();
|
this.material = item.getItem().getType();
|
||||||
|
|
||||||
ItemMeta meta = item.getItem().getItemMeta();
|
ItemMeta meta = item.getItem().getItemMeta();
|
||||||
this.displayName = meta.hasDisplayName() ? meta.getDisplayName() : null;
|
if (meta != null) { this.displayName = meta.hasDisplayName() ? meta.getDisplayName() : null; } else { this.displayName = null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public Material getType() {
|
public Material getType() {
|
||||||
|
@ -1,49 +1,184 @@
|
|||||||
package net.Indyuce.mmoitems.api.crafting.recipe;
|
package net.Indyuce.mmoitems.api.crafting.recipe;
|
||||||
|
|
||||||
|
import io.lumine.mythic.lib.api.crafting.uimanager.ProvidedUIFilter;
|
||||||
|
import io.lumine.mythic.lib.api.crafting.uimanager.UIFilterManager;
|
||||||
import io.lumine.mythic.lib.api.util.SmartGive;
|
import io.lumine.mythic.lib.api.util.SmartGive;
|
||||||
|
import io.lumine.mythic.lib.api.util.ui.FriendlyFeedbackCategory;
|
||||||
|
import io.lumine.mythic.lib.api.util.ui.FriendlyFeedbackMessage;
|
||||||
|
import io.lumine.mythic.lib.api.util.ui.FriendlyFeedbackProvider;
|
||||||
|
import io.lumine.mythic.lib.api.util.ui.SilentNumbers;
|
||||||
|
import net.Indyuce.mmoitems.MMOItems;
|
||||||
import net.Indyuce.mmoitems.api.crafting.ConfigMMOItem;
|
import net.Indyuce.mmoitems.api.crafting.ConfigMMOItem;
|
||||||
import net.Indyuce.mmoitems.api.crafting.CraftingStation;
|
import net.Indyuce.mmoitems.api.crafting.CraftingStation;
|
||||||
import net.Indyuce.mmoitems.api.crafting.CraftingStatus.CraftingQueue;
|
import net.Indyuce.mmoitems.api.crafting.CraftingStatus.CraftingQueue;
|
||||||
|
import net.Indyuce.mmoitems.api.crafting.MMOItemUIFilter;
|
||||||
import net.Indyuce.mmoitems.api.crafting.ingredient.inventory.IngredientInventory;
|
import net.Indyuce.mmoitems.api.crafting.ingredient.inventory.IngredientInventory;
|
||||||
import net.Indyuce.mmoitems.api.event.PlayerUseCraftingStationEvent;
|
import net.Indyuce.mmoitems.api.event.PlayerUseCraftingStationEvent;
|
||||||
|
import net.Indyuce.mmoitems.api.item.template.MMOItemTemplate;
|
||||||
import net.Indyuce.mmoitems.api.item.util.ConfigItems;
|
import net.Indyuce.mmoitems.api.item.util.ConfigItems;
|
||||||
import net.Indyuce.mmoitems.api.player.PlayerData;
|
import net.Indyuce.mmoitems.api.player.PlayerData;
|
||||||
|
import net.Indyuce.mmoitems.api.player.RPGPlayer;
|
||||||
|
import net.Indyuce.mmoitems.api.util.message.FFPMMOItems;
|
||||||
import net.Indyuce.mmoitems.api.util.message.Message;
|
import net.Indyuce.mmoitems.api.util.message.Message;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.ChatColor;
|
import org.bukkit.ChatColor;
|
||||||
import org.bukkit.Sound;
|
import org.bukkit.Sound;
|
||||||
import org.bukkit.configuration.ConfigurationSection;
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
public class CraftingRecipe extends Recipe {
|
public class CraftingRecipe extends Recipe {
|
||||||
private final ConfigMMOItem output;
|
@NotNull public static final String UNSPECIFIED = "N/A";
|
||||||
|
|
||||||
|
public CraftingRecipe(@NotNull ConfigurationSection config) throws IllegalArgumentException {
|
||||||
|
super(config);
|
||||||
|
|
||||||
|
craftingTime = config.getDouble("crafting-time");
|
||||||
|
|
||||||
|
// Legacy loading
|
||||||
|
String uiFilter = config.getString("output.item", UNSPECIFIED);
|
||||||
|
String miType = config.getString("output.type", UNSPECIFIED).toUpperCase().replace("-", "_").replace(" ", "_");
|
||||||
|
String miID = config.getString("output.id", UNSPECIFIED).toUpperCase().replace("-", "_").replace(" ", "_");
|
||||||
|
|
||||||
|
// Yes
|
||||||
|
FriendlyFeedbackProvider ffp = new FriendlyFeedbackProvider(FFPMMOItems.get());
|
||||||
|
|
||||||
|
// Both legacy specified?
|
||||||
|
if (!UNSPECIFIED.equals(miType) && !UNSPECIFIED.equals(miID)) {
|
||||||
|
|
||||||
|
// Generate filter
|
||||||
|
ProvidedUIFilter sweetOutput = UIFilterManager.getUIFilter("m", miType, miID, config.getString("output.amount", "1"), ffp);
|
||||||
|
|
||||||
|
// Is it null?
|
||||||
|
if (sweetOutput == null) {
|
||||||
|
|
||||||
|
// Throw message
|
||||||
|
throw new IllegalArgumentException(SilentNumbers.collapseList(SilentNumbers.transcribeList(ffp.getFeedbackOf(FriendlyFeedbackCategory.ERROR), message -> { if (message instanceof FriendlyFeedbackMessage) { return ((FriendlyFeedbackMessage) message).forConsole(FFPMMOItems.get()); } return ""; }), ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accept
|
||||||
|
output = sweetOutput;
|
||||||
|
|
||||||
|
// New method specified?
|
||||||
|
} else if (!UNSPECIFIED.equals(uiFilter)) {
|
||||||
|
|
||||||
|
// Generate filter
|
||||||
|
ProvidedUIFilter sweetOutput = UIFilterManager.getUIFilter(uiFilter, ffp);
|
||||||
|
|
||||||
|
// Is it null?
|
||||||
|
if (sweetOutput == null) {
|
||||||
|
|
||||||
|
// Throw message
|
||||||
|
throw new IllegalArgumentException(SilentNumbers.collapseList(SilentNumbers.transcribeList(ffp.getFeedbackOf(FriendlyFeedbackCategory.ERROR), message -> { if (message instanceof FriendlyFeedbackMessage) { return ((FriendlyFeedbackMessage) message).forConsole(FFPMMOItems.get()); } return ""; }), ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accept
|
||||||
|
output = sweetOutput;
|
||||||
|
|
||||||
|
// Invalid filter
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// Throw message
|
||||||
|
throw new IllegalArgumentException(FriendlyFeedbackProvider.quickForConsole(FFPMMOItems.get(), "Config must contain a valid Type and ID, or a valid UIFilter. "));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Valid UIFilter?
|
||||||
|
if (!output.isValid(ffp)) {
|
||||||
|
|
||||||
|
// Throw message
|
||||||
|
throw new IllegalArgumentException(SilentNumbers.collapseList(SilentNumbers.transcribeList(ffp.getFeedbackOf(FriendlyFeedbackCategory.ERROR), message -> { if (message instanceof FriendlyFeedbackMessage) { return ((FriendlyFeedbackMessage) message).forConsole(FFPMMOItems.get()); } return ""; }), ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Valid UIFilter?
|
||||||
|
if (output.getItemStack(ffp) == null) {
|
||||||
|
|
||||||
|
// Throw message
|
||||||
|
throw new IllegalArgumentException(SilentNumbers.collapseList(SilentNumbers.transcribeList(ffp.getFeedbackOf(FriendlyFeedbackCategory.ERROR), message -> { if (message instanceof FriendlyFeedbackMessage) { return ((FriendlyFeedbackMessage) message).forConsole(FFPMMOItems.get()); } return ""; }), ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Its a MMOItem UIFilter, then?
|
||||||
|
if (output.getParent() instanceof MMOItemUIFilter) {
|
||||||
|
|
||||||
|
// Find template
|
||||||
|
MMOItemTemplate template = MMOItems.plugin.getTemplates().getTemplate(MMOItems.plugin.getTypes().get(output.getArgument()), output.getData());
|
||||||
|
|
||||||
|
// Not possible tho
|
||||||
|
if (template == null) {
|
||||||
|
|
||||||
|
// Throw message
|
||||||
|
throw new IllegalArgumentException(FriendlyFeedbackProvider.quickForConsole(FFPMMOItems.get(), "This should be impossible, please contact $egunging$b: $fThe ProvidedUIFilter was flagged as 'valid' but clearly is not. $enet.Indyuce.mmoitems.api.crafting.recipe$b. "));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Identify MMOItems operation
|
||||||
|
identifiedMMO = new ConfigMMOItem(template, output.getAmount(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* There can't be any crafting time for upgrading recipes since there is no
|
* There can't be any crafting time for upgrading recipes since there is no
|
||||||
* way to save an MMOItem in the config file TODO save as ItemStack
|
* way to save an MMOItem in the config file TODO save as ItemStack
|
||||||
*/
|
*/
|
||||||
private final double craftingTime;
|
private final double craftingTime;
|
||||||
|
public double getCraftingTime() { return craftingTime; }
|
||||||
|
public boolean isInstant() { return craftingTime <= 0; }
|
||||||
|
|
||||||
public CraftingRecipe(ConfigurationSection config) {
|
/**
|
||||||
super(config);
|
* @return The item specified by the player that will be produced by this recipe.
|
||||||
|
*/
|
||||||
|
@NotNull public ProvidedUIFilter getOutput() { return output; }
|
||||||
|
@NotNull private final ProvidedUIFilter output;
|
||||||
|
|
||||||
craftingTime = config.getDouble("crafting-time");
|
@Nullable ConfigMMOItem identifiedMMO;
|
||||||
|
/**
|
||||||
|
* @return The output ItemStack from this
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("ConstantConditions")
|
||||||
|
@NotNull public ItemStack getOutputItemStack(@Nullable RPGPlayer rpg) {
|
||||||
|
|
||||||
// load recipe output
|
// Generate as MMOItem
|
||||||
output = new ConfigMMOItem(config.getConfigurationSection("output"));
|
if (identifiedMMO != null && rpg != null) {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Generate in the legacy way. I do this way to preserve
|
||||||
|
* backwards compatibility, since this is how it used to
|
||||||
|
* be done. Don't want to break that without good reason.
|
||||||
|
*/
|
||||||
|
return identifiedMMO.generate(rpg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate from ProvidedUIFilter, guaranteed to not be null don't listen to the inspection.
|
||||||
|
return output.getItemStack(null);
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @return The preview ItemStack from this
|
||||||
|
*/
|
||||||
|
@NotNull public ItemStack getPreviewItemStack() {
|
||||||
|
|
||||||
public double getCraftingTime() {
|
// Generate as MMOItem
|
||||||
return craftingTime;
|
if (identifiedMMO != null) {
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isInstant() {
|
/*
|
||||||
return craftingTime <= 0;
|
* Generate in the legacy way. I do this way to preserve
|
||||||
}
|
* backwards compatibility, since this is how it used to
|
||||||
|
* be done. Don't want to break that without good reason.
|
||||||
|
*/
|
||||||
|
return identifiedMMO.getPreview();
|
||||||
|
}
|
||||||
|
|
||||||
public ConfigMMOItem getOutput() {
|
// Generate from ProvidedUIFilter, guaranteed to not be null don't listen to the inspection.
|
||||||
return output;
|
//return output.getParent().getDisplayStack(output.getArgument(), output.getData(), null);
|
||||||
|
//return output.getDisplayStack(null);
|
||||||
|
ItemStack gen = output.getParent().getDisplayStack(output.getArgument(), output.getData(), null);
|
||||||
|
gen.setAmount(output.getAmount(1));
|
||||||
|
ItemMeta itemMeta = gen.getItemMeta();
|
||||||
|
if (itemMeta != null) {
|
||||||
|
itemMeta.setDisplayName(SilentNumbers.getItemName(gen, false) + "\u00a7\u02ab");
|
||||||
|
gen.setItemMeta(itemMeta); }
|
||||||
|
return gen;
|
||||||
}
|
}
|
||||||
|
public int getOutputAmount() { return output.getAmount(1); }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean whenUsed(PlayerData data, IngredientInventory inv, CheckedRecipe recipe, CraftingStation station) {
|
public boolean whenUsed(PlayerData data, IngredientInventory inv, CheckedRecipe recipe, CraftingStation station) {
|
||||||
@ -57,7 +192,7 @@ public class CraftingRecipe extends Recipe {
|
|||||||
*/
|
*/
|
||||||
if (isInstant()) {
|
if (isInstant()) {
|
||||||
|
|
||||||
ItemStack result = hasOption(RecipeOption.OUTPUT_ITEM) ? getOutput().generate(data.getRPG()) : null;
|
ItemStack result = hasOption(RecipeOption.OUTPUT_ITEM) ? getOutputItemStack(data.getRPG()) : null;
|
||||||
PlayerUseCraftingStationEvent event = new PlayerUseCraftingStationEvent(data, station, recipe, result);
|
PlayerUseCraftingStationEvent event = new PlayerUseCraftingStationEvent(data, station, recipe, result);
|
||||||
Bukkit.getPluginManager().callEvent(event);
|
Bukkit.getPluginManager().callEvent(event);
|
||||||
if (event.isCancelled())
|
if (event.isCancelled())
|
||||||
@ -113,9 +248,7 @@ public class CraftingRecipe extends Recipe {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ItemStack display(CheckedRecipe recipe) {
|
public ItemStack display(CheckedRecipe recipe) { return ConfigItems.CRAFTING_RECIPE_DISPLAY.newBuilder(recipe).build(); }
|
||||||
return ConfigItems.CRAFTING_RECIPE_DISPLAY.newBuilder(recipe).build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CheckedRecipe evaluateRecipe(PlayerData data, IngredientInventory inv) {
|
public CheckedRecipe evaluateRecipe(PlayerData data, IngredientInventory inv) {
|
||||||
|
@ -0,0 +1,94 @@
|
|||||||
|
package net.Indyuce.mmoitems.api.event;
|
||||||
|
|
||||||
|
import io.lumine.mythic.lib.api.item.NBTItem;
|
||||||
|
import io.lumine.mythic.lib.damage.DamageType;
|
||||||
|
import io.lumine.mythic.lib.player.PlayerMetadata;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.event.Event;
|
||||||
|
import org.bukkit.event.HandlerList;
|
||||||
|
import org.bukkit.event.entity.EntityShootBowEvent;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when a MMOItems arrow or trident entity is fired.
|
||||||
|
* <br><br>
|
||||||
|
* Contains information even on the temporary stats the player had when
|
||||||
|
* they executed the action, if that matters for some reason...
|
||||||
|
* <br><br>
|
||||||
|
* Note that this event fires before the projectile actually registers,
|
||||||
|
* be mindful of changes made to the temporary stats because they will
|
||||||
|
* affect the projectile.
|
||||||
|
*/
|
||||||
|
public class MMOItemsProjectileFireEvent extends Event {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The item the player used to fire this arrow.
|
||||||
|
*/
|
||||||
|
@NotNull public NBTItem getSourceItem() { return sourceItem; }
|
||||||
|
@NotNull NBTItem sourceItem;
|
||||||
|
/**
|
||||||
|
* Note that you must use {@link #setFinalDamage(double)} to modify the attack
|
||||||
|
* damage of the projectile rather than editing the attack damage of the player
|
||||||
|
* in here, as it will get overwritten.
|
||||||
|
*
|
||||||
|
* @return The stats the player had at the moment of firing the projectile.
|
||||||
|
*/
|
||||||
|
@NotNull public PlayerMetadata getPlayerStatsSnapshot() { return playerStatsSnapshot; }
|
||||||
|
@NotNull PlayerMetadata playerStatsSnapshot;
|
||||||
|
/**
|
||||||
|
* @return The projectile entity that was fired, arrow or trident.
|
||||||
|
*/
|
||||||
|
@NotNull public Entity getProjectile() { return projectile; }
|
||||||
|
@NotNull Entity projectile;
|
||||||
|
/**
|
||||||
|
* @return The damage this projectile will deal
|
||||||
|
*/
|
||||||
|
public double getFinalDamage() { return finalDamage; }
|
||||||
|
double finalDamage;
|
||||||
|
/**
|
||||||
|
* @param damage The damage this projectile will deal
|
||||||
|
*/
|
||||||
|
public void setFinalDamage(double damage) { finalDamage = damage; }
|
||||||
|
/**
|
||||||
|
* @return The original damage amount
|
||||||
|
*/
|
||||||
|
public double getDamageMultiplicator() { return damageMultiplicator; }
|
||||||
|
double damageMultiplicator;
|
||||||
|
/**
|
||||||
|
* @return The original damage amount
|
||||||
|
*/
|
||||||
|
public double getOriginalDamage() { return originalDamage; }
|
||||||
|
double originalDamage;
|
||||||
|
/**
|
||||||
|
* @return The kinds of damage this projectile will deal, what it will scale with.
|
||||||
|
*/
|
||||||
|
@NotNull public DamageType[] getDamageTypes() { return damageTypes; }
|
||||||
|
@NotNull DamageType[] damageTypes = { DamageType.PROJECTILE, DamageType.PHYSICAL, DamageType.WEAPON };
|
||||||
|
/**
|
||||||
|
* @param types The kinds of damage this projectile will deal, what it will scale with.
|
||||||
|
*/
|
||||||
|
public void setDamageTypes(@NotNull DamageType[] types) { damageTypes = types; }
|
||||||
|
/**
|
||||||
|
* @return The event that caused this projectile to be fired. Honestly, only for informational purposes of whatever listening API.
|
||||||
|
*/
|
||||||
|
@Nullable public EntityShootBowEvent getEvent() { return event; }
|
||||||
|
@Nullable EntityShootBowEvent event;
|
||||||
|
|
||||||
|
public MMOItemsProjectileFireEvent(@NotNull PlayerMetadata player, @NotNull Entity projectile, @NotNull NBTItem item, @Nullable EntityShootBowEvent event, double originalDamage, double damageMultiplicator) {
|
||||||
|
playerStatsSnapshot = player;
|
||||||
|
this.projectile = projectile;
|
||||||
|
sourceItem = item;
|
||||||
|
this.originalDamage = originalDamage;
|
||||||
|
this.damageMultiplicator= damageMultiplicator;
|
||||||
|
finalDamage = originalDamage * damageMultiplicator;
|
||||||
|
this.event = event;
|
||||||
|
}
|
||||||
|
|
||||||
|
//region Event Standard
|
||||||
|
private static final HandlerList handlers = new HandlerList();
|
||||||
|
@NotNull
|
||||||
|
@Override public HandlerList getHandlers() { return handlers; }
|
||||||
|
public static HandlerList getHandlerList() { return handlers; }
|
||||||
|
//endregion
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
package net.Indyuce.mmoitems.api.event;
|
||||||
|
|
||||||
|
import net.Indyuce.mmoitems.api.interaction.UseItem;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.entity.LivingEntity;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.Cancellable;
|
||||||
|
import org.bukkit.event.HandlerList;
|
||||||
|
import org.bukkit.event.player.PlayerEvent;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
public class MMOItemsSpecialWeaponAttack extends PlayerEvent implements Cancellable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The weapon used by the player that fired this event
|
||||||
|
*/
|
||||||
|
@NotNull public UseItem getWeapon() { return weapon; }
|
||||||
|
@NotNull final UseItem weapon;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The entity that is being hit by this special attack
|
||||||
|
*/
|
||||||
|
@Nullable public LivingEntity getTarget() { return target; }
|
||||||
|
@Nullable final LivingEntity target;
|
||||||
|
|
||||||
|
public MMOItemsSpecialWeaponAttack(@NotNull Player who, @NotNull UseItem weapon, @Nullable LivingEntity target) {
|
||||||
|
super(who);
|
||||||
|
this.weapon = weapon;
|
||||||
|
this.target = target;
|
||||||
|
}
|
||||||
|
|
||||||
|
//region Event Standard
|
||||||
|
private static final HandlerList handlers = new HandlerList();
|
||||||
|
@NotNull @Override public HandlerList getHandlers() { return handlers; }
|
||||||
|
public static HandlerList getHandlerList() { return handlers; }
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
//region Cancellable Standard
|
||||||
|
boolean cancelled;
|
||||||
|
@Override public boolean isCancelled() {
|
||||||
|
return cancelled;
|
||||||
|
}
|
||||||
|
@Override public void setCancelled(boolean cancel) {
|
||||||
|
cancelled = cancel;
|
||||||
|
}
|
||||||
|
//endregion
|
||||||
|
}
|
@ -17,6 +17,7 @@ import net.Indyuce.mmoitems.api.player.PlayerData.CooldownType;
|
|||||||
import org.bukkit.Color;
|
import org.bukkit.Color;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Sound;
|
import org.bukkit.Sound;
|
||||||
|
import org.bukkit.entity.LivingEntity;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.util.Vector;
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
@ -67,4 +68,27 @@ public class Musket extends UntargetedWeapon {
|
|||||||
trace.draw(loc, vec, 2, Color.BLACK);
|
trace.draw(loc, vec, 2, Color.BLACK);
|
||||||
getPlayer().getWorld().playSound(getPlayer().getLocation(), Sound.ENTITY_ZOMBIE_ATTACK_IRON_DOOR, 2, 2);
|
getPlayer().getWorld().playSound(getPlayer().getLocation(), Sound.ENTITY_ZOMBIE_ATTACK_IRON_DOOR, 2, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LivingEntity untargetedTargetTrace(EquipmentSlot slot) {
|
||||||
|
|
||||||
|
// Temporary Stats
|
||||||
|
PlayerMetadata stats = getPlayerData().getStats().newTemporary(slot);
|
||||||
|
|
||||||
|
// Range
|
||||||
|
double range = getValue(getNBTItem().getStat(ItemStats.RANGE.getId()), MMOItems.plugin.getConfig().getDouble("default.range"));
|
||||||
|
double a = Math.toRadians(getPlayer().getEyeLocation().getYaw() + 160);
|
||||||
|
Location loc = getPlayer().getEyeLocation().add(new Vector(Math.cos(a), 0, Math.sin(a)).multiply(.5));
|
||||||
|
Vector vec = loc.getDirection();
|
||||||
|
|
||||||
|
// Raytrace
|
||||||
|
MMORayTraceResult trace = MythicLib.plugin.getVersion().getWrapper().rayTrace(stats.getPlayer(), vec, range,
|
||||||
|
entity -> MMOUtils.canTarget(stats.getPlayer(), entity, InteractionType.OFFENSE_ACTION));
|
||||||
|
|
||||||
|
// Find entity
|
||||||
|
if (trace.hasHit()) { return trace.getHit(); }
|
||||||
|
|
||||||
|
// No
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,6 +69,26 @@ public class Staff extends UntargetedWeapon {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LivingEntity untargetedTargetTrace(EquipmentSlot slot) {
|
||||||
|
|
||||||
|
// Temporary Stats
|
||||||
|
PlayerMetadata stats = getPlayerData().getStats().newTemporary(slot);
|
||||||
|
|
||||||
|
// Range
|
||||||
|
double range = getValue(getNBTItem().getStat(ItemStats.RANGE.getId()), MMOItems.plugin.getConfig().getDouble("default.range"));
|
||||||
|
|
||||||
|
// Raytrace
|
||||||
|
MMORayTraceResult trace = MythicLib.plugin.getVersion().getWrapper().rayTrace(stats.getPlayer(), range,
|
||||||
|
entity -> MMOUtils.canTarget(stats.getPlayer(), entity, InteractionType.OFFENSE_ACTION));
|
||||||
|
|
||||||
|
// Find Entity
|
||||||
|
if (trace.hasHit()) { return trace.getHit(); }
|
||||||
|
|
||||||
|
// Nothing Found
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public void specialAttack(LivingEntity target) {
|
public void specialAttack(LivingEntity target) {
|
||||||
if (!MMOItems.plugin.getConfig().getBoolean("item-ability.staff.enabled"))
|
if (!MMOItems.plugin.getConfig().getBoolean("item-ability.staff.enabled"))
|
||||||
return;
|
return;
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
package net.Indyuce.mmoitems.api.interaction.weapon.untargeted;
|
package net.Indyuce.mmoitems.api.interaction.weapon.untargeted;
|
||||||
|
|
||||||
import io.lumine.mythic.lib.api.player.EquipmentSlot;
|
import io.lumine.mythic.lib.api.player.EquipmentSlot;
|
||||||
|
import org.bukkit.entity.LivingEntity;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.block.Action;
|
import org.bukkit.event.block.Action;
|
||||||
|
|
||||||
import net.Indyuce.mmoitems.api.interaction.weapon.Weapon;
|
import net.Indyuce.mmoitems.api.interaction.weapon.Weapon;
|
||||||
import io.lumine.mythic.lib.api.item.NBTItem;
|
import io.lumine.mythic.lib.api.item.NBTItem;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
public abstract class UntargetedWeapon extends Weapon {
|
public abstract class UntargetedWeapon extends Weapon {
|
||||||
protected final WeaponType weaponType;
|
protected final WeaponType weaponType;
|
||||||
@ -24,6 +26,14 @@ public abstract class UntargetedWeapon extends Weapon {
|
|||||||
*/
|
*/
|
||||||
public abstract void untargetedAttack(EquipmentSlot slot);
|
public abstract void untargetedAttack(EquipmentSlot slot);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Predicts which target will be get hit when using {@link #untargetedAttack(EquipmentSlot)}
|
||||||
|
* with the same exact information, this way the target is available beforehand.
|
||||||
|
*
|
||||||
|
* @param slot Slot being interacted with
|
||||||
|
*/
|
||||||
|
@Nullable public LivingEntity untargetedTargetTrace(EquipmentSlot slot) { return null; }
|
||||||
|
|
||||||
public WeaponType getWeaponType() {
|
public WeaponType getWeaponType() {
|
||||||
return weaponType;
|
return weaponType;
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ import net.Indyuce.mmoitems.api.interaction.util.UntargetedDurabilityItem;
|
|||||||
import net.Indyuce.mmoitems.api.player.PlayerData.CooldownType;
|
import net.Indyuce.mmoitems.api.player.PlayerData.CooldownType;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Particle;
|
import org.bukkit.Particle;
|
||||||
|
import org.bukkit.entity.LivingEntity;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.util.Vector;
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
@ -54,4 +55,26 @@ public class Whip extends UntargetedWeapon {
|
|||||||
(tick) -> tick.getWorld().spawnParticle(Particle.CRIT, tick, 0, .1, .1, .1, 0));
|
(tick) -> tick.getWorld().spawnParticle(Particle.CRIT, tick, 0, .1, .1, .1, 0));
|
||||||
getPlayer().getWorld().playSound(getPlayer().getLocation(), VersionSound.ENTITY_FIREWORK_ROCKET_BLAST.toSound(), 1, 2);
|
getPlayer().getWorld().playSound(getPlayer().getLocation(), VersionSound.ENTITY_FIREWORK_ROCKET_BLAST.toSound(), 1, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LivingEntity untargetedTargetTrace(EquipmentSlot slot) {
|
||||||
|
|
||||||
|
// Temporary Stats
|
||||||
|
PlayerMetadata stats = getPlayerData().getStats().newTemporary(slot);
|
||||||
|
|
||||||
|
// Range
|
||||||
|
double range = getValue(getNBTItem().getStat(ItemStats.RANGE.getId()), MMOItems.plugin.getConfig().getDouble("default.range"));
|
||||||
|
double a = Math.toRadians(getPlayer().getEyeLocation().getYaw() + 160);
|
||||||
|
Location loc = getPlayer().getEyeLocation().add(new Vector(Math.cos(a), 0, Math.sin(a)).multiply(.5));
|
||||||
|
|
||||||
|
// Ray Trace
|
||||||
|
MMORayTraceResult trace = MythicLib.plugin.getVersion().getWrapper().rayTrace(stats.getPlayer(), range,
|
||||||
|
entity -> MMOUtils.canTarget(stats.getPlayer(), entity, InteractionType.OFFENSE_ACTION));
|
||||||
|
|
||||||
|
// Find entity
|
||||||
|
if (trace.hasHit()) { return trace.getHit(); }
|
||||||
|
|
||||||
|
// No
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -178,9 +178,7 @@ public class ItemStackBuilder {
|
|||||||
|
|
||||||
// Get Template
|
// Get Template
|
||||||
MMOItemTemplate template = MMOItems.plugin.getTemplates().getTemplate(builtMMOItem.getType(), builtMMOItem.getId());
|
MMOItemTemplate template = MMOItems.plugin.getTemplates().getTemplate(builtMMOItem.getType(), builtMMOItem.getId());
|
||||||
if (template == null) {
|
if (template == null) { throw new IllegalArgumentException("MMOItem $r" + builtMMOItem.getType().getId() + " " + builtMMOItem.getId() + "$b doesn't exist."); }
|
||||||
throw new IllegalArgumentException("MMOItem $r" + builtMMOItem.getType().getId() + " " + builtMMOItem.getId() + "$b doesn't exist.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make necessary lore changes
|
// Make necessary lore changes
|
||||||
((Previewable) stat).whenPreviewed(this, builtMMOItem.getData(stat), template.getBaseItemData().get(stat));
|
((Previewable) stat).whenPreviewed(this, builtMMOItem.getData(stat), template.getBaseItemData().get(stat));
|
||||||
@ -195,11 +193,8 @@ public class ItemStackBuilder {
|
|||||||
} catch (IllegalArgumentException | NullPointerException exception) {
|
} catch (IllegalArgumentException | NullPointerException exception) {
|
||||||
|
|
||||||
// That
|
// That
|
||||||
MMOItems.plugin.getLogger().log(Level.WARNING, FriendlyFeedbackProvider.quickForConsole(FFPMMOItems.get(),
|
MMOItems.print(Level.WARNING, "An error occurred while trying to generate item '$f{0}$b' with stat '$f{1}$b': {2}",
|
||||||
"An error occurred while trying to generate item '$f{0}$b' with stat '$f{1}$b': {2}",
|
"ItemStackBuilder", builtMMOItem.getId(), stat.getId(), exception.getMessage());
|
||||||
builtMMOItem.getId(),
|
|
||||||
stat.getId(),
|
|
||||||
exception.getMessage()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display gem stone lore hint thing
|
// Display gem stone lore hint thing
|
||||||
|
@ -109,11 +109,11 @@ public class CraftingRecipeDisplay extends ConfigItem {
|
|||||||
lore.add(conditionsIndex++, condition.format());
|
lore.add(conditionsIndex++, condition.format());
|
||||||
}
|
}
|
||||||
|
|
||||||
ItemStack item = craftingRecipe.getOutput().getPreview();
|
ItemStack item = craftingRecipe.getPreviewItemStack();
|
||||||
int amount = craftingRecipe.getOutput().getAmount();
|
int amount = craftingRecipe.getOutputAmount();
|
||||||
|
|
||||||
if (amount > 64)
|
if (amount > 64)
|
||||||
lore.add(0, Message.STATION_BIG_STACK.format(ChatColor.GOLD, "#size#", "" + amount).toString());
|
lore.add(0, Message.STATION_BIG_STACK.format(ChatColor.GOLD, "#size#", String.valueOf(amount)).toString());
|
||||||
else
|
else
|
||||||
item.setAmount(amount);
|
item.setAmount(amount);
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ public class QueueItemDisplay extends ConfigItem {
|
|||||||
for (String key : replace.keySet())
|
for (String key : replace.keySet())
|
||||||
lore.set(lore.indexOf(key), replace.get(key).replace("#left#", formatDelay(crafting.getLeft())));
|
lore.set(lore.indexOf(key), replace.get(key).replace("#left#", formatDelay(crafting.getLeft())));
|
||||||
|
|
||||||
ItemStack item = crafting.getRecipe().getOutput().getPreview();
|
ItemStack item = crafting.getRecipe().getPreviewItemStack();
|
||||||
item.setAmount(position);
|
item.setAmount(position);
|
||||||
ItemMeta meta = item.getItemMeta();
|
ItemMeta meta = item.getItemMeta();
|
||||||
meta.addItemFlags(ItemFlag.values());
|
meta.addItemFlags(ItemFlag.values());
|
||||||
|
@ -1,33 +1,46 @@
|
|||||||
package net.Indyuce.mmoitems.comp.mmocore;
|
package net.Indyuce.mmoitems.comp.mmocore;
|
||||||
|
|
||||||
|
import io.lumine.mythic.lib.version.VersionMaterial;
|
||||||
import net.Indyuce.mmocore.MMOCore;
|
import net.Indyuce.mmocore.MMOCore;
|
||||||
import net.Indyuce.mmocore.api.event.PlayerChangeClassEvent;
|
import net.Indyuce.mmocore.api.event.PlayerChangeClassEvent;
|
||||||
import net.Indyuce.mmocore.api.event.PlayerLevelUpEvent;
|
import net.Indyuce.mmocore.api.event.PlayerLevelUpEvent;
|
||||||
import net.Indyuce.mmocore.api.event.PlayerResourceUpdateEvent;
|
import net.Indyuce.mmocore.api.event.PlayerResourceUpdateEvent;
|
||||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||||
import net.Indyuce.mmocore.api.player.attribute.PlayerAttribute;
|
import net.Indyuce.mmocore.api.player.attribute.PlayerAttribute;
|
||||||
|
import net.Indyuce.mmocore.api.player.stats.StatType;
|
||||||
import net.Indyuce.mmocore.experience.Profession;
|
import net.Indyuce.mmocore.experience.Profession;
|
||||||
import net.Indyuce.mmoitems.MMOItems;
|
import net.Indyuce.mmoitems.MMOItems;
|
||||||
import net.Indyuce.mmoitems.api.player.RPGPlayer;
|
import net.Indyuce.mmoitems.api.player.RPGPlayer;
|
||||||
import net.Indyuce.mmoitems.comp.mmocore.stat.Required_Attribute;
|
import net.Indyuce.mmoitems.comp.mmocore.stat.Required_Attribute;
|
||||||
import net.Indyuce.mmoitems.comp.mmocore.stat.Required_Profession;
|
import net.Indyuce.mmoitems.comp.mmocore.stat.Required_Profession;
|
||||||
import net.Indyuce.mmoitems.comp.rpg.RPGHandler;
|
import net.Indyuce.mmoitems.comp.rpg.RPGHandler;
|
||||||
|
import net.Indyuce.mmoitems.stat.type.DoubleStat;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
public class MMOCoreHook implements RPGHandler, Listener {
|
public class MMOCoreHook implements RPGHandler, Listener {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when MMOItems enables
|
* Called when MMOItems enables
|
||||||
* <p>
|
* <p>
|
||||||
* These stats are only updated on a server reload because that
|
* These stats are only updated on a server reload because that
|
||||||
* class has to be instanciated again for the registered stats to update
|
* class has to be instantiated again for the registered stats to update
|
||||||
*/
|
*/
|
||||||
public MMOCoreHook() {
|
public MMOCoreHook() {
|
||||||
for (PlayerAttribute attribute : MMOCore.plugin.attributeManager.getAll())
|
for (PlayerAttribute attribute : MMOCore.plugin.attributeManager.getAll())
|
||||||
MMOItems.plugin.getStats().register(new Required_Attribute(attribute));
|
MMOItems.plugin.getStats().register(new Required_Attribute(attribute));
|
||||||
for (Profession profession : MMOCore.plugin.professionManager.getAll())
|
for (Profession profession : MMOCore.plugin.professionManager.getAll()) {
|
||||||
|
|
||||||
|
// Adds profession specific Additional Experience stats.
|
||||||
|
MMOItems.plugin.getStats().register(new DoubleStat((StatType.ADDITIONAL_EXPERIENCE.name() + '_' + profession.getId())
|
||||||
|
.replace('-', '_').replace(' ', '_').toUpperCase(Locale.ROOT),
|
||||||
|
VersionMaterial.EXPERIENCE_BOTTLE.toMaterial(), profession.getName() + ' ' + "Additional Experience (MMOCore)"
|
||||||
|
, new String[]{"Additional MMOCore profession " + profession.getName() + " experience in %."}, new String[]{"!block", "all"}));
|
||||||
|
|
||||||
MMOItems.plugin.getStats().register(new Required_Profession(profession));
|
MMOItems.plugin.getStats().register(new Required_Profession(profession));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
package net.Indyuce.mmoitems.comp.mythicmobs;
|
package net.Indyuce.mmoitems.comp.mythicmobs;
|
||||||
|
|
||||||
import io.lumine.xikage.mythicmobs.MythicMobs;
|
import io.lumine.xikage.mythicmobs.MythicMobs;
|
||||||
|
import io.lumine.xikage.mythicmobs.api.bukkit.events.MythicMechanicLoadEvent;
|
||||||
import io.lumine.xikage.mythicmobs.api.bukkit.events.MythicReloadedEvent;
|
import io.lumine.xikage.mythicmobs.api.bukkit.events.MythicReloadedEvent;
|
||||||
import io.lumine.xikage.mythicmobs.mobs.MythicMob;
|
import io.lumine.xikage.mythicmobs.mobs.MythicMob;
|
||||||
import net.Indyuce.mmoitems.MMOItems;
|
import net.Indyuce.mmoitems.MMOItems;
|
||||||
import net.Indyuce.mmoitems.api.item.mmoitem.MMOItem;
|
import net.Indyuce.mmoitems.api.item.mmoitem.MMOItem;
|
||||||
import net.Indyuce.mmoitems.api.player.PlayerData;
|
import net.Indyuce.mmoitems.api.player.PlayerData;
|
||||||
|
import net.Indyuce.mmoitems.comp.mythicmobs.mechanics.MMOItemsArrowVolleyMechanic;
|
||||||
|
import net.Indyuce.mmoitems.comp.mythicmobs.mechanics.MMOItemsOnShootAura;
|
||||||
import net.Indyuce.mmoitems.comp.mythicmobs.stat.FactionDamage;
|
import net.Indyuce.mmoitems.comp.mythicmobs.stat.FactionDamage;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
@ -29,6 +32,22 @@ public class MythicMobsCompatibility implements Listener {
|
|||||||
Bukkit.getPluginManager().registerEvents(this, MMOItems.plugin);
|
Bukkit.getPluginManager().registerEvents(this, MMOItems.plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@EventHandler(priority = EventPriority.HIGH)
|
||||||
|
public void b(MythicMechanicLoadEvent event) {
|
||||||
|
|
||||||
|
// Switch Mechanic ig
|
||||||
|
switch (event.getMechanicName().toLowerCase()) {
|
||||||
|
case "mmoitemsvolley":
|
||||||
|
event.register(new MMOItemsArrowVolleyMechanic(event.getContainer().getConfigLine(), event.getConfig()));
|
||||||
|
break;
|
||||||
|
case "onmmoitemuse":
|
||||||
|
event.register(new MMOItemsOnShootAura(event.getContainer().getConfigLine(), event.getConfig()));
|
||||||
|
break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MythicLib skill handlers are reloaded on priority {@link EventPriority#NORMAL}
|
* MythicLib skill handlers are reloaded on priority {@link EventPriority#NORMAL}
|
||||||
* MMOCore and MMOItems use HIGH or HIGHEST
|
* MMOCore and MMOItems use HIGH or HIGHEST
|
||||||
|
@ -0,0 +1,187 @@
|
|||||||
|
package net.Indyuce.mmoitems.comp.mythicmobs.mechanics;
|
||||||
|
|
||||||
|
import io.lumine.mythic.lib.api.crafting.uimanager.ProvidedUIFilter;
|
||||||
|
import io.lumine.mythic.lib.api.crafting.uimanager.UIFilterManager;
|
||||||
|
import io.lumine.xikage.mythicmobs.adapters.AbstractEntity;
|
||||||
|
import io.lumine.xikage.mythicmobs.adapters.AbstractLocation;
|
||||||
|
import io.lumine.xikage.mythicmobs.adapters.SkillAdapter;
|
||||||
|
import io.lumine.xikage.mythicmobs.adapters.bukkit.BukkitAdapter;
|
||||||
|
import io.lumine.xikage.mythicmobs.io.MythicLineConfig;
|
||||||
|
import io.lumine.xikage.mythicmobs.skills.*;
|
||||||
|
import io.lumine.xikage.mythicmobs.skills.placeholders.parsers.PlaceholderDouble;
|
||||||
|
import io.lumine.xikage.mythicmobs.skills.placeholders.parsers.PlaceholderFloat;
|
||||||
|
import io.lumine.xikage.mythicmobs.skills.placeholders.parsers.PlaceholderInt;
|
||||||
|
import net.Indyuce.mmoitems.MMOItems;
|
||||||
|
import net.Indyuce.mmoitems.listener.ItemUse;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.entity.Arrow;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.entity.EntityShootBowEvent;
|
||||||
|
import org.bukkit.inventory.EquipmentSlot;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An arrow volley method but uses the stats of the bow
|
||||||
|
* held by the player that is casting this skill, or at
|
||||||
|
* least a scaled version of them!
|
||||||
|
*
|
||||||
|
* @author Gunging
|
||||||
|
*/
|
||||||
|
public class MMOItemsArrowVolleyMechanic extends SkillMechanic implements ITargetedEntitySkill, ITargetedLocationSkill {
|
||||||
|
|
||||||
|
@NotNull PlaceholderInt amount, spread, fireTicks, removeDelay;
|
||||||
|
@NotNull PlaceholderFloat velocity, scale;
|
||||||
|
@NotNull PlaceholderDouble xOffset, yOffset, zOffset, fOffset, sOffset;
|
||||||
|
|
||||||
|
@Nullable ItemStack arrowItem;
|
||||||
|
boolean fullEvent;
|
||||||
|
boolean scalePerArrow;
|
||||||
|
boolean fromOrigin;
|
||||||
|
|
||||||
|
public MMOItemsArrowVolleyMechanic(String line, MythicLineConfig mlc) {
|
||||||
|
super(line, mlc);
|
||||||
|
threadSafetyLevel = ThreadSafetyLevel.SYNC_ONLY;
|
||||||
|
|
||||||
|
amount = mlc.getPlaceholderInteger(new String[] {"amount", "arrows", "a"}, 20);
|
||||||
|
spread = mlc.getPlaceholderInteger(new String[] {"spread", "s"}, 45);
|
||||||
|
fireTicks = mlc.getPlaceholderInteger(new String[] {"fireticks", "ft", "f"}, 0);
|
||||||
|
removeDelay = mlc.getPlaceholderInteger(new String[] {"removedelay", "rd", "r"}, 200);
|
||||||
|
velocity = mlc.getPlaceholderFloat(new String[] {"velocity", "v"}, 20);
|
||||||
|
scale = mlc.getPlaceholderFloat(new String[] {"statsscale", "ss"}, 1);
|
||||||
|
|
||||||
|
fullEvent = mlc.getBoolean(new String[] {"fullevent", "fe"}, false);
|
||||||
|
scalePerArrow = mlc.getBoolean(new String[] {"scaleperarrow", "spa"}, false);
|
||||||
|
fromOrigin = mlc.getBoolean(new String[] {"fromorigin", "fo"}, false);
|
||||||
|
|
||||||
|
//region Get Arrow Item
|
||||||
|
String itemFilter = mlc.getString(new String[] {"arrowitem", "item", "ai"}, null);
|
||||||
|
if (itemFilter != null) {
|
||||||
|
ProvidedUIFilter uiFilter = UIFilterManager.getUIFilter(itemFilter, null);
|
||||||
|
if (uiFilter != null) {
|
||||||
|
if (uiFilter.isValid(null) && uiFilter.getParent().fullyDefinesItem()) {
|
||||||
|
uiFilter.setAmount(1);
|
||||||
|
|
||||||
|
// Generate Item
|
||||||
|
arrowItem = uiFilter.getItemStack(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
// Offsets
|
||||||
|
xOffset = mlc.getPlaceholderDouble(new String[] {"startxoffset", "sxo"}, 0);
|
||||||
|
yOffset = mlc.getPlaceholderDouble(new String[] {"startyoffset", "syo"}, 3);
|
||||||
|
zOffset = mlc.getPlaceholderDouble(new String[] {"startzoffset", "szo"}, 0);
|
||||||
|
fOffset = mlc.getPlaceholderDouble(new String[] {"startfoffset", "sfo"}, 0);
|
||||||
|
sOffset = mlc.getPlaceholderDouble(new String[] {"startsoffset", "sso"}, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean castAtLocation(SkillMetadata data, AbstractLocation target) {
|
||||||
|
|
||||||
|
// Caster must be a player
|
||||||
|
if (data.getCaster().getEntity().getBukkitEntity() instanceof Player) {
|
||||||
|
|
||||||
|
// MMOItems Volley!
|
||||||
|
executeMIVolley(data.getCaster(), data, target, amount.get(data), velocity.get(data) * 0.1F, spread.get(data), fireTicks.get(data), removeDelay.get(data), scale);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// Run as normal mythicmobs arrow volley
|
||||||
|
SkillAdapter.get().executeVolley(data.getCaster(), target, amount.get(data), velocity.get(data) * 0.1F, spread.get(data), fireTicks.get(data), removeDelay.get(data));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean castAtEntity(SkillMetadata data, AbstractEntity target) {
|
||||||
|
|
||||||
|
// Caster must be a player
|
||||||
|
if (data.getCaster().getEntity().getBukkitEntity() instanceof Player) {
|
||||||
|
|
||||||
|
// MMOItems Volley!
|
||||||
|
executeMIVolley(data.getCaster(), data, target.getLocation(), amount.get(data,target), velocity.get(data) * 0.1F, spread.get(data), fireTicks.get(data), removeDelay.get(data), scale);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// Run as normal mythicmobs arrow volley
|
||||||
|
SkillAdapter.get().executeVolley(data.getCaster(), target.getLocation(), amount.get(data,target), velocity.get(data) * 0.1F, spread.get(data), fireTicks.get(data), removeDelay.get(data));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void executeMIVolley(@NotNull SkillCaster caster, @NotNull SkillMetadata data, @NotNull AbstractLocation t, int amount, float velocity, float spread, int fireTicks, int removeDelay, @NotNull PlaceholderFloat statsMultiplier) {
|
||||||
|
|
||||||
|
// Skill caster MUST be a player
|
||||||
|
if (!(caster.getEntity().getBukkitEntity() instanceof Player)) { return; }
|
||||||
|
Player player = (Player) caster.getEntity().getBukkitEntity();
|
||||||
|
|
||||||
|
// Target yeah
|
||||||
|
Location target = BukkitAdapter.adapt(t);
|
||||||
|
Location spawn = BukkitAdapter.adapt(fromOrigin ? data.getOrigin() : caster.getLocation()).clone();
|
||||||
|
|
||||||
|
//region Calculate Offsets
|
||||||
|
Vector forward = spawn.getDirection().normalize();
|
||||||
|
Vector side = (new Vector(-forward.getZ(), 0.00001, forward.getX())).normalize();
|
||||||
|
|
||||||
|
double fS = fOffset.get(data);
|
||||||
|
double sS = sOffset.get(data);
|
||||||
|
|
||||||
|
spawn.setX(spawn.getX() + xOffset.get(data) + (forward.getX() * fS) + (side.getX() * sS));
|
||||||
|
spawn.setY(spawn.getY() + yOffset.get(data) + (forward.getY() * fS) + (side.getY() * sS));
|
||||||
|
spawn.setZ(spawn.getZ() + zOffset.get(data) + (forward.getZ() * fS) + (side.getZ() * sS));
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
// Direction vector
|
||||||
|
Vector v = target.toVector().subtract(spawn.toVector()).normalize();
|
||||||
|
|
||||||
|
// Player bow item is held??
|
||||||
|
ItemStack bowItem = player.getInventory().getItemInMainHand().clone();
|
||||||
|
ItemStack localArrowItem = (arrowItem != null ? arrowItem.clone() : new ItemStack(Material.ARROW));
|
||||||
|
ItemUse use = new ItemUse();
|
||||||
|
|
||||||
|
// Parse
|
||||||
|
float arrowForce = statsMultiplier.get(data);
|
||||||
|
|
||||||
|
// Spawn arrows
|
||||||
|
ArrayList<Arrow> arrowList = new ArrayList<>();
|
||||||
|
for (int i = 0; i < amount; i++) {
|
||||||
|
|
||||||
|
// Spawn Arrow
|
||||||
|
Arrow a = player.getWorld().spawnArrow(spawn, v, velocity, (spread/10.0F));
|
||||||
|
a.setVelocity(a.getVelocity());
|
||||||
|
|
||||||
|
// Identify arrow as the player's
|
||||||
|
a.setShooter(player);
|
||||||
|
|
||||||
|
// Run Event
|
||||||
|
EntityShootBowEvent shootBowEvent = new EntityShootBowEvent(player, bowItem, localArrowItem, a, EquipmentSlot.HAND, arrowForce, false);
|
||||||
|
if (fullEvent) { Bukkit.getPluginManager().callEvent(shootBowEvent); } else { use.handleCustomBows(shootBowEvent); }
|
||||||
|
|
||||||
|
// Cancelled???
|
||||||
|
if (shootBowEvent.isCancelled()) { a.remove(); continue; }
|
||||||
|
|
||||||
|
// Set on fire I guess
|
||||||
|
if(fireTicks > 0) { a.setFireTicks(fireTicks); }
|
||||||
|
|
||||||
|
// Add to list
|
||||||
|
arrowList.add(a);
|
||||||
|
|
||||||
|
// Recalculate
|
||||||
|
if (scalePerArrow) { arrowForce = statsMultiplier.get(data); }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove after delay
|
||||||
|
Bukkit.getScheduler().scheduleSyncDelayedTask(MMOItems.plugin, () -> {
|
||||||
|
for (Arrow a : arrowList) { a.remove(); }arrowList.clear(); }, removeDelay);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,211 @@
|
|||||||
|
package net.Indyuce.mmoitems.comp.mythicmobs.mechanics;
|
||||||
|
|
||||||
|
import io.lumine.xikage.mythicmobs.MythicMobs;
|
||||||
|
import io.lumine.xikage.mythicmobs.adapters.AbstractEntity;
|
||||||
|
import io.lumine.xikage.mythicmobs.adapters.bukkit.BukkitAdapter;
|
||||||
|
import io.lumine.xikage.mythicmobs.io.MythicLineConfig;
|
||||||
|
import io.lumine.xikage.mythicmobs.mobs.GenericCaster;
|
||||||
|
import io.lumine.xikage.mythicmobs.skills.*;
|
||||||
|
import io.lumine.xikage.mythicmobs.skills.auras.Aura;
|
||||||
|
import io.lumine.xikage.mythicmobs.skills.placeholders.parsers.PlaceholderString;
|
||||||
|
import io.lumine.xikage.mythicmobs.utils.Events;
|
||||||
|
import net.Indyuce.mmoitems.MMOItems;
|
||||||
|
import net.Indyuce.mmoitems.api.event.MMOItemsSpecialWeaponAttack;
|
||||||
|
import net.Indyuce.mmoitems.api.interaction.weapon.Gauntlet;
|
||||||
|
import net.Indyuce.mmoitems.api.interaction.weapon.untargeted.*;
|
||||||
|
import org.bukkit.scheduler.BukkitRunnable;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sure there is the 'onShoot' aura for bows, but what about
|
||||||
|
* musket and crossbow and lute and...?
|
||||||
|
*
|
||||||
|
* This Aura will cover all of those.
|
||||||
|
*
|
||||||
|
* @author Gunging
|
||||||
|
*/
|
||||||
|
public class MMOItemsOnShootAura extends Aura implements ITargetedEntitySkill {
|
||||||
|
@NotNull PlaceholderString skillName;
|
||||||
|
@NotNull String weaponTypes;
|
||||||
|
@Nullable Skill metaskill;
|
||||||
|
boolean cancelEvent;
|
||||||
|
boolean forceAsPower;
|
||||||
|
|
||||||
|
@NotNull final ArrayList<UseItemTypes> auraWeapons = new ArrayList<>();
|
||||||
|
|
||||||
|
public MMOItemsOnShootAura(String skill, MythicLineConfig mlc) {
|
||||||
|
super(skill, mlc);
|
||||||
|
skillName = mlc.getPlaceholderString(new String[]{"skill", "s", "ondamagedskill", "ondamaged", "od", "onhitskill", "onhit", "oh", "meta", "m", "mechanics", "$", "()"}, "skill not found");
|
||||||
|
weaponTypes = mlc.getString(new String[]{"weapons", "weapon", "w"}, "MUSKET");
|
||||||
|
metaskill = GetSkill(skillName.get());
|
||||||
|
cancelEvent = mlc.getBoolean(new String[]{"cancelevent", "ce"}, false);
|
||||||
|
|
||||||
|
// Parse weapon types
|
||||||
|
ArrayList<String> weaponTypesUnparsed = new ArrayList<>();
|
||||||
|
if (weaponTypes.contains(",")) { weaponTypesUnparsed.addAll(Arrays.asList(weaponTypes.split(","))); } else { weaponTypesUnparsed.add(weaponTypes); }
|
||||||
|
|
||||||
|
for (String weapon : weaponTypesUnparsed) {
|
||||||
|
// Try to get
|
||||||
|
try {
|
||||||
|
|
||||||
|
// Parse
|
||||||
|
UseItemTypes weap = UseItemTypes.valueOf(weapon.toUpperCase());
|
||||||
|
|
||||||
|
// Yes
|
||||||
|
auraWeapons.add(weap);
|
||||||
|
|
||||||
|
} catch (IllegalArgumentException ignored) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attempt to fix meta skill
|
||||||
|
if (metaskill == null) {
|
||||||
|
//MM//OotilityCeption.Log("\u00a7c--->> \u00a7eMeta Skill Failure \u00a7c<<---");
|
||||||
|
|
||||||
|
// Try again i guess?
|
||||||
|
(new BukkitRunnable() {
|
||||||
|
public void run() {
|
||||||
|
|
||||||
|
// Run Async
|
||||||
|
metaskill = GetSkill(skillName.get());
|
||||||
|
|
||||||
|
}
|
||||||
|
}).runTaskLater(MMOItems.plugin, 1L);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean castAtEntity(SkillMetadata data, AbstractEntity target) {
|
||||||
|
// Find caster
|
||||||
|
SkillCaster caster;
|
||||||
|
|
||||||
|
// Will be caster of the skill, as a mythicmob
|
||||||
|
if (MythicMobs.inst().getMobManager().isActiveMob(target)) {
|
||||||
|
//SOM//OotilityCeption.Log("\u00a73 * \u00a77Target as ActiveMob");
|
||||||
|
|
||||||
|
// Just pull the mythicmob
|
||||||
|
caster = MythicMobs.inst().getMobManager().getMythicMobInstance(target);
|
||||||
|
|
||||||
|
// If its a player or some other non-mythicmob
|
||||||
|
} else {
|
||||||
|
//SOM//OotilityCeption.Log("\u00a73 * \u00a77Target as Non MM");
|
||||||
|
|
||||||
|
// I guess make a new caster out of them
|
||||||
|
caster = new GenericCaster(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
new MMOItemsOnShootAura.Tracker(caster, data, target);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Tracker extends AuraTracker implements IParentSkill, Runnable {
|
||||||
|
public Tracker(SkillCaster caster, SkillMetadata data, AbstractEntity entity) {
|
||||||
|
super(caster, entity, data);
|
||||||
|
this.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void auraStart() {
|
||||||
|
this.registerAuraComponent(Events.subscribe(MMOItemsSpecialWeaponAttack.class).filter((event) -> {
|
||||||
|
|
||||||
|
//SOM//OotilityCeption.Log("\u00a7cStep 3 \u00a77Subscribe Run: " + getName(event.getEntity()) + "\u00a77 vs " + getName(this.entity.get()) + "\u00a78 ~\u00a7e " + event.getEntity().getUniqueId().equals(this.entity.get().getUniqueId()));
|
||||||
|
|
||||||
|
// Player is the one who has the aura applied, right?
|
||||||
|
if (!event.getPlayer().getUniqueId().equals(this.entity.get().getUniqueId())) { return false; }
|
||||||
|
|
||||||
|
// All custom weapons fire it if none specified.
|
||||||
|
if (auraWeapons.size() == 0) { return true; }
|
||||||
|
|
||||||
|
// Okay go through all weapon types, must match one
|
||||||
|
for (UseItemTypes weap : auraWeapons) {
|
||||||
|
if (weap.getInst().isInstance(event.getWeapon())) { return true; } }
|
||||||
|
|
||||||
|
// None matched
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}).handler((event) -> {
|
||||||
|
|
||||||
|
// Clone metadata
|
||||||
|
SkillMetadata meta = this.skillMetadata.deepClone();
|
||||||
|
|
||||||
|
// Refresh
|
||||||
|
if (metaskill == null) { metaskill = GetSkill(skillName.get(meta, meta.getCaster().getEntity())); }
|
||||||
|
|
||||||
|
// Target obviously the projectile
|
||||||
|
AbstractEntity target = BukkitAdapter.adapt(event.getTarget());
|
||||||
|
meta.setTrigger(target);
|
||||||
|
|
||||||
|
//SOM//OotilityCeption.Log("\u00a7cStep 4 \u00a77Aura Run:\u00a7d " + logSkillData(meta) + "\u00a7b " + metaskill.getInternalName());
|
||||||
|
if (this.executeAuraSkill(Optional.ofNullable(metaskill), meta)) {
|
||||||
|
|
||||||
|
this.consumeCharge();
|
||||||
|
|
||||||
|
if (cancelEvent) { event.setCancelled(true); }
|
||||||
|
}
|
||||||
|
|
||||||
|
}));
|
||||||
|
this.executeAuraSkill(MMOItemsOnShootAura.this.onStartSkill, this.skillMetadata);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable public static Skill GetSkill(String skillName) {
|
||||||
|
|
||||||
|
if (SkillExists(skillName)) {
|
||||||
|
|
||||||
|
Optional<Skill> mSkillFk = MythicMobs.inst().getSkillManager().getSkill(skillName);
|
||||||
|
if (mSkillFk == null) { return null; }
|
||||||
|
if (mSkillFk.isPresent()) { return mSkillFk.get(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
public static boolean SkillExists(String skillName) {
|
||||||
|
// If null no
|
||||||
|
if (skillName == null) { return false; }
|
||||||
|
|
||||||
|
Optional<Skill> mSkillFk = MythicMobs.inst().getSkillManager().getSkill(skillName);
|
||||||
|
|
||||||
|
// Is there a skill of that name?
|
||||||
|
if (mSkillFk.isPresent()) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Ok then retrieve the skill
|
||||||
|
Skill mSkill = (Skill) mSkillFk.get();
|
||||||
|
|
||||||
|
// Success
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
|
||||||
|
// RIP
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The skill was not found
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// False means the skill does not exist.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum UseItemTypes {
|
||||||
|
CROSSBOW(Crossbow.class),
|
||||||
|
GAUNTLET(Gauntlet.class),
|
||||||
|
LUTE(Lute.class),
|
||||||
|
MUSKET(Musket.class),
|
||||||
|
STAFF(Staff.class),
|
||||||
|
WHIP(Whip.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Class to use InstanceOf and identify a weapon.
|
||||||
|
*/
|
||||||
|
@NotNull public Class getInst() { return inst; }
|
||||||
|
@NotNull final Class inst;
|
||||||
|
UseItemTypes(@NotNull Class inst) {
|
||||||
|
this.inst = inst;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -20,6 +20,7 @@ import org.bukkit.event.inventory.InventoryClickEvent;
|
|||||||
import org.bukkit.inventory.Inventory;
|
import org.bukkit.inventory.Inventory;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.inventory.meta.ItemMeta;
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -40,6 +41,7 @@ public class CraftingStationPreview extends PluginInventory {
|
|||||||
this.recipe = recipe;
|
this.recipe = recipe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Inventory getInventory() {
|
public Inventory getInventory() {
|
||||||
|
|
||||||
@ -105,8 +107,8 @@ public class CraftingStationPreview extends PluginInventory {
|
|||||||
inv.setItem(slot, ConfigItems.FILL.getItem());
|
inv.setItem(slot, ConfigItems.FILL.getItem());
|
||||||
|
|
||||||
if (recipe.getRecipe() instanceof CraftingRecipe) {
|
if (recipe.getRecipe() instanceof CraftingRecipe) {
|
||||||
ItemStack item = ((CraftingRecipe) recipe.getRecipe()).getOutput().getPreview();
|
ItemStack item = ((CraftingRecipe) recipe.getRecipe()).getPreviewItemStack();
|
||||||
item.setAmount(((CraftingRecipe) recipe.getRecipe()).getOutput().getAmount());
|
item.setAmount(((CraftingRecipe) recipe.getRecipe()).getOutputAmount());
|
||||||
inv.setItem(16, item);
|
inv.setItem(16, item);
|
||||||
}
|
}
|
||||||
if (recipe.getRecipe() instanceof UpgradingRecipe) {
|
if (recipe.getRecipe() instanceof UpgradingRecipe) {
|
||||||
|
@ -181,7 +181,7 @@ public class CraftingStationView extends PluginInventory {
|
|||||||
* to the player and remove the recipe from the queue
|
* to the player and remove the recipe from the queue
|
||||||
*/
|
*/
|
||||||
if (recipeInfo.isReady()) {
|
if (recipeInfo.isReady()) {
|
||||||
ItemStack result = recipe.hasOption(Recipe.RecipeOption.OUTPUT_ITEM) ? recipe.getOutput().generate(playerData.getRPG()) : null;
|
ItemStack result = recipe.hasOption(Recipe.RecipeOption.OUTPUT_ITEM) ? recipe.getOutputItemStack(playerData.getRPG()) : null;
|
||||||
|
|
||||||
PlayerUseCraftingStationEvent called = new PlayerUseCraftingStationEvent(playerData, station, recipe, result);
|
PlayerUseCraftingStationEvent called = new PlayerUseCraftingStationEvent(playerData, station, recipe, result);
|
||||||
Bukkit.getPluginManager().callEvent(called);
|
Bukkit.getPluginManager().callEvent(called);
|
||||||
|
@ -69,7 +69,7 @@ public class AbilityEdition extends EditionInventory {
|
|||||||
if (ability != null) {
|
if (ability != null) {
|
||||||
String castModeConfigString = getEditedSection().getString("ability." + configKey + ".mode");
|
String castModeConfigString = getEditedSection().getString("ability." + configKey + ".mode");
|
||||||
String castModeFormat = castModeConfigString == null ? ""
|
String castModeFormat = castModeConfigString == null ? ""
|
||||||
: castModeConfigString.toUpperCase().replace(" ", "_").replace("-", "_").replaceAll("[^A-Z_]", "");
|
: castModeConfigString.toUpperCase().replace(" ", "_").replace("-", "_").replaceAll("[^A-Z0-9_]", "");
|
||||||
TriggerType castMode = TriggerType.safeValueOf(castModeFormat);
|
TriggerType castMode = TriggerType.safeValueOf(castModeFormat);
|
||||||
|
|
||||||
ItemStack castModeItem = new ItemStack(Material.ARMOR_STAND);
|
ItemStack castModeItem = new ItemStack(Material.ARMOR_STAND);
|
||||||
|
@ -12,6 +12,8 @@ import net.Indyuce.mmoitems.MMOUtils;
|
|||||||
import net.Indyuce.mmoitems.api.ItemAttackMetadata;
|
import net.Indyuce.mmoitems.api.ItemAttackMetadata;
|
||||||
import net.Indyuce.mmoitems.api.Type;
|
import net.Indyuce.mmoitems.api.Type;
|
||||||
import net.Indyuce.mmoitems.api.TypeSet;
|
import net.Indyuce.mmoitems.api.TypeSet;
|
||||||
|
import net.Indyuce.mmoitems.api.event.MMOItemsProjectileFireEvent;
|
||||||
|
import net.Indyuce.mmoitems.api.event.MMOItemsSpecialWeaponAttack;
|
||||||
import net.Indyuce.mmoitems.api.interaction.*;
|
import net.Indyuce.mmoitems.api.interaction.*;
|
||||||
import net.Indyuce.mmoitems.api.interaction.weapon.Gauntlet;
|
import net.Indyuce.mmoitems.api.interaction.weapon.Gauntlet;
|
||||||
import net.Indyuce.mmoitems.api.interaction.weapon.Weapon;
|
import net.Indyuce.mmoitems.api.interaction.weapon.Weapon;
|
||||||
@ -20,6 +22,7 @@ import net.Indyuce.mmoitems.api.interaction.weapon.untargeted.UntargetedWeapon;
|
|||||||
import net.Indyuce.mmoitems.api.interaction.weapon.untargeted.UntargetedWeapon.WeaponType;
|
import net.Indyuce.mmoitems.api.interaction.weapon.untargeted.UntargetedWeapon.WeaponType;
|
||||||
import net.Indyuce.mmoitems.api.player.PlayerData;
|
import net.Indyuce.mmoitems.api.player.PlayerData;
|
||||||
import net.Indyuce.mmoitems.api.util.message.Message;
|
import net.Indyuce.mmoitems.api.util.message.Message;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.ChatColor;
|
import org.bukkit.ChatColor;
|
||||||
import org.bukkit.GameMode;
|
import org.bukkit.GameMode;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
@ -95,10 +98,21 @@ public class ItemUse implements Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (useItem instanceof UntargetedWeapon) {
|
if (useItem instanceof UntargetedWeapon) {
|
||||||
|
|
||||||
UntargetedWeapon weapon = (UntargetedWeapon) useItem;
|
UntargetedWeapon weapon = (UntargetedWeapon) useItem;
|
||||||
if ((event.getAction().name().contains("RIGHT_CLICK") && weapon.getWeaponType() == WeaponType.RIGHT_CLICK)
|
if ((event.getAction().name().contains("RIGHT_CLICK") && weapon.getWeaponType() == WeaponType.RIGHT_CLICK)
|
||||||
|| (event.getAction().name().contains("LEFT_CLICK") && weapon.getWeaponType() == WeaponType.LEFT_CLICK))
|
|| (event.getAction().name().contains("LEFT_CLICK") && weapon.getWeaponType() == WeaponType.LEFT_CLICK)) {
|
||||||
|
MMOItems.log("Running from \u00a7cUNTARGETTED");
|
||||||
|
|
||||||
|
// Run attack event
|
||||||
|
MMOItemsSpecialWeaponAttack attackEvent = new MMOItemsSpecialWeaponAttack(player, useItem, weapon.untargetedTargetTrace(EquipmentSlot.fromBukkit(event.getHand())));
|
||||||
|
Bukkit.getPluginManager().callEvent(attackEvent);
|
||||||
|
|
||||||
|
// Cancelled?
|
||||||
|
if (attackEvent.isCancelled()) { return; }
|
||||||
|
|
||||||
weapon.untargetedAttack(EquipmentSlot.fromBukkit(event.getHand()));
|
weapon.untargetedAttack(EquipmentSlot.fromBukkit(event.getHand()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,12 +200,33 @@ public class ItemUse implements Listener {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Special staff attack
|
// Special staff attack
|
||||||
if (weapon instanceof Staff)
|
if (weapon instanceof Staff) {
|
||||||
|
MMOItems.log("Running from \u00a7aSTAFF");
|
||||||
|
// Run attack event
|
||||||
|
MMOItemsSpecialWeaponAttack attackEvent = new MMOItemsSpecialWeaponAttack(player, weapon, target);
|
||||||
|
Bukkit.getPluginManager().callEvent(attackEvent);
|
||||||
|
|
||||||
|
// Cancelled?
|
||||||
|
if (attackEvent.isCancelled()) { return; }
|
||||||
|
|
||||||
|
// Run attack
|
||||||
((Staff) weapon).specialAttack(target);
|
((Staff) weapon).specialAttack(target);
|
||||||
|
}
|
||||||
|
|
||||||
// Special gauntlet attack
|
// Special gauntlet attack
|
||||||
if (weapon instanceof Gauntlet)
|
if (weapon instanceof Gauntlet) {
|
||||||
|
MMOItems.log("Running from \u00a7bGAUNTLET");
|
||||||
|
|
||||||
|
// Run attack event
|
||||||
|
MMOItemsSpecialWeaponAttack attackEvent = new MMOItemsSpecialWeaponAttack(player, weapon, target);
|
||||||
|
Bukkit.getPluginManager().callEvent(attackEvent);
|
||||||
|
|
||||||
|
// Cancelled?
|
||||||
|
if (attackEvent.isCancelled()) { return; }
|
||||||
|
|
||||||
|
// Run attack
|
||||||
((Gauntlet) weapon).specialAttack(target);
|
((Gauntlet) weapon).specialAttack(target);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Rewrite this with a custom 'ApplyMMOItemEvent'?
|
// TODO: Rewrite this with a custom 'ApplyMMOItemEvent'?
|
||||||
@ -289,8 +324,7 @@ public class ItemUse implements Listener {
|
|||||||
Arrow arrow = (Arrow) event.getProjectile();
|
Arrow arrow = (Arrow) event.getProjectile();
|
||||||
if (item.getStat("ARROW_VELOCITY") > 0)
|
if (item.getStat("ARROW_VELOCITY") > 0)
|
||||||
arrow.setVelocity(arrow.getVelocity().multiply(item.getStat("ARROW_VELOCITY")));
|
arrow.setVelocity(arrow.getVelocity().multiply(item.getStat("ARROW_VELOCITY")));
|
||||||
MMOItems.plugin.getEntities().registerCustomProjectile(item, playerData.getStats().newTemporary(bowSlot), event.getProjectile(), type != null,
|
MMOItems.plugin.getEntities().registerCustomProjectile(item, playerData.getStats().newTemporary(bowSlot), event.getProjectile(), event, type != null, event.getForce());
|
||||||
event.getForce());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -22,6 +22,7 @@ import org.bukkit.Material;
|
|||||||
import org.bukkit.configuration.ConfigurationSection;
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
import org.bukkit.potion.PotionEffectType;
|
import org.bukkit.potion.PotionEffectType;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -255,8 +256,8 @@ public class ConfigManager implements Reloadable {
|
|||||||
return configName != null ? configName : ability.getName();
|
return configName != null ? configName : ability.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getCastingModeName(TriggerType mode) {
|
@NotNull public String getCastingModeName(@NotNull TriggerType mode) {
|
||||||
return abilities.getConfig().getString("cast-mode." + mode.getLowerCaseId());
|
return abilities.getConfig().getString("cast-mode." + mode.getLowerCaseId(), mode.name());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
|
@ -6,6 +6,7 @@ import io.lumine.mythic.lib.damage.DamageType;
|
|||||||
import io.lumine.mythic.lib.player.PlayerMetadata;
|
import io.lumine.mythic.lib.player.PlayerMetadata;
|
||||||
import net.Indyuce.mmoitems.MMOItems;
|
import net.Indyuce.mmoitems.MMOItems;
|
||||||
import net.Indyuce.mmoitems.api.ItemAttackMetadata;
|
import net.Indyuce.mmoitems.api.ItemAttackMetadata;
|
||||||
|
import net.Indyuce.mmoitems.api.event.MMOItemsProjectileFireEvent;
|
||||||
import net.Indyuce.mmoitems.api.interaction.projectile.ArrowParticles;
|
import net.Indyuce.mmoitems.api.interaction.projectile.ArrowParticles;
|
||||||
import net.Indyuce.mmoitems.api.interaction.projectile.EntityData;
|
import net.Indyuce.mmoitems.api.interaction.projectile.EntityData;
|
||||||
import net.Indyuce.mmoitems.api.interaction.projectile.ProjectileData;
|
import net.Indyuce.mmoitems.api.interaction.projectile.ProjectileData;
|
||||||
@ -20,6 +21,9 @@ import org.bukkit.event.EventPriority;
|
|||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||||
import org.bukkit.event.entity.EntityDeathEvent;
|
import org.bukkit.event.entity.EntityDeathEvent;
|
||||||
|
import org.bukkit.event.entity.EntityShootBowEvent;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -36,10 +40,8 @@ public class EntityManager implements Listener {
|
|||||||
|
|
||||||
private final WeakHashMap<Integer, ProjectileData> projectiles = new WeakHashMap<>();
|
private final WeakHashMap<Integer, ProjectileData> projectiles = new WeakHashMap<>();
|
||||||
|
|
||||||
public void registerCustomProjectile(NBTItem sourceItem, PlayerMetadata attacker, Entity entity, boolean customWeapon) {
|
@Deprecated public void registerCustomProjectile(NBTItem sourceItem, PlayerMetadata attacker, Entity entity, boolean customWeapon) { registerCustomProjectile(sourceItem, attacker, entity, customWeapon, 1); }
|
||||||
registerCustomProjectile(sourceItem, attacker, entity, customWeapon, 1);
|
@Deprecated public void registerCustomProjectile(@NotNull NBTItem sourceItem, @NotNull PlayerMetadata attacker, @NotNull Entity entity, boolean customWeapon, double damageMultiplicator) { registerCustomProjectile(sourceItem, attacker, entity, null, customWeapon, damageMultiplicator); }
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a custom projectile. This is used for bows, crossbows and tridents.
|
* Registers a custom projectile. This is used for bows, crossbows and tridents.
|
||||||
* <p>
|
* <p>
|
||||||
@ -47,12 +49,13 @@ public class EntityManager implements Listener {
|
|||||||
*
|
*
|
||||||
* @param sourceItem Item used to shoot the projectile
|
* @param sourceItem Item used to shoot the projectile
|
||||||
* @param attacker Cached stats of the player shooting the projectile
|
* @param attacker Cached stats of the player shooting the projectile
|
||||||
|
* @param shootEvent Event that caused this projectile registration.
|
||||||
* @param entity The custom entity
|
* @param entity The custom entity
|
||||||
* @param customWeapon Is the source weapon is a custom item
|
* @param customWeapon Is the source weapon is a custom item
|
||||||
* @param damageMultiplicator The damage coefficient. For bows, this is basically the pull force.
|
* @param damageMultiplicator The damage coefficient. For bows, this is basically the pull force.
|
||||||
* For tridents or anything else this is always set to 1
|
* For tridents or anything else this is always set to 1
|
||||||
*/
|
*/
|
||||||
public void registerCustomProjectile(NBTItem sourceItem, PlayerMetadata attacker, Entity entity, boolean customWeapon, double damageMultiplicator) {
|
public void registerCustomProjectile(@NotNull NBTItem sourceItem, @NotNull PlayerMetadata attacker, @NotNull Entity entity, @Nullable EntityShootBowEvent shootEvent, boolean customWeapon, double damageMultiplicator) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For bows, MC default value is 7. When using custom bows, the attack
|
* For bows, MC default value is 7. When using custom bows, the attack
|
||||||
@ -64,10 +67,16 @@ public class EntityManager implements Listener {
|
|||||||
* and 1 for bows, and it's always 1 for tridents or crossbows.
|
* and 1 for bows, and it's always 1 for tridents or crossbows.
|
||||||
*/
|
*/
|
||||||
double damage = attacker.getStat("ATTACK_DAMAGE");
|
double damage = attacker.getStat("ATTACK_DAMAGE");
|
||||||
damage = (customWeapon ? damage : 5 + damage) * damageMultiplicator;
|
|
||||||
|
|
||||||
ItemAttackMetadata attackMeta = new ItemAttackMetadata(new DamageMetadata(damage, DamageType.WEAPON, DamageType.PHYSICAL, DamageType.PROJECTILE), attacker);
|
// Sweet event
|
||||||
attacker.setStat("ATTACK_DAMAGE", damage);
|
MMOItemsProjectileFireEvent event = new MMOItemsProjectileFireEvent(attacker, entity, sourceItem, shootEvent, (customWeapon ? damage : 5 + damage), damageMultiplicator);
|
||||||
|
Bukkit.getPluginManager().callEvent(event);
|
||||||
|
|
||||||
|
// Update based one vent
|
||||||
|
double finalDamage = event.getFinalDamage();
|
||||||
|
|
||||||
|
ItemAttackMetadata attackMeta = new ItemAttackMetadata(new DamageMetadata(finalDamage, event.getDamageTypes()), attacker);
|
||||||
|
attacker.setStat("ATTACK_DAMAGE", finalDamage);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Load arrow particles if the entity is an arrow and if the item has
|
* Load arrow particles if the entity is an arrow and if the item has
|
||||||
|
@ -113,7 +113,8 @@ public class Abilities extends ItemStat {
|
|||||||
String configKey = (String) info[0];
|
String configKey = (String) info[0];
|
||||||
String edited = (String) info[1];
|
String edited = (String) info[1];
|
||||||
|
|
||||||
String format = message.toUpperCase().replace("-", "_").replace(" ", "_").replaceAll("[^A-Z_]", "");
|
String format = message.toUpperCase().replace("-", "_").replace(" ", "_").replaceAll("[^A-Z0-9_]", "");
|
||||||
|
|
||||||
if (edited.equals("ability")) {
|
if (edited.equals("ability")) {
|
||||||
Validate.isTrue(MMOItems.plugin.getSkills().hasSkill(format),
|
Validate.isTrue(MMOItems.plugin.getSkills().hasSkill(format),
|
||||||
"format is not a valid ability! You may check the ability list using /mi list ability.");
|
"format is not a valid ability! You may check the ability list using /mi list ability.");
|
||||||
@ -128,7 +129,9 @@ public class Abilities extends ItemStat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (edited.equals("mode")) {
|
if (edited.equals("mode")) {
|
||||||
|
|
||||||
TriggerType castMode = TriggerType.valueOf(format);
|
TriggerType castMode = TriggerType.valueOf(format);
|
||||||
|
|
||||||
inv.getEditedSection().set("ability." + configKey + ".mode", castMode.name());
|
inv.getEditedSection().set("ability." + configKey + ".mode", castMode.name());
|
||||||
inv.registerTemplateEdition();
|
inv.registerTemplateEdition();
|
||||||
inv.getPlayer().sendMessage(MMOItems.plugin.getPrefix() + "Successfully set the trigger to " + ChatColor.GOLD + castMode.getName()
|
inv.getPlayer().sendMessage(MMOItems.plugin.getPrefix() + "Successfully set the trigger to " + ChatColor.GOLD + castMode.getName()
|
||||||
|
@ -28,8 +28,8 @@ import java.util.Set;
|
|||||||
|
|
||||||
public class AbilityData extends Skill {
|
public class AbilityData extends Skill {
|
||||||
private final RegisteredSkill ability;
|
private final RegisteredSkill ability;
|
||||||
private final TriggerType triggerType;
|
@NotNull private final TriggerType triggerType;
|
||||||
private final Map<String, Double> modifiers = new HashMap<>();
|
@NotNull private final Map<String, Double> modifiers = new HashMap<>();
|
||||||
|
|
||||||
public AbilityData(JsonObject object) {
|
public AbilityData(JsonObject object) {
|
||||||
ability = MMOItems.plugin.getSkills().getSkill(object.get("Id").getAsString());
|
ability = MMOItems.plugin.getSkills().getSkill(object.get("Id").getAsString());
|
||||||
@ -63,9 +63,7 @@ public class AbilityData extends Skill {
|
|||||||
return ability;
|
return ability;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TriggerType getTriggerType() {
|
@NotNull public TriggerType getTriggerType() { return triggerType; }
|
||||||
return triggerType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set<String> getModifiers() {
|
public Set<String> getModifiers() {
|
||||||
return modifiers.keySet();
|
return modifiers.keySet();
|
||||||
@ -80,7 +78,6 @@ public class AbilityData extends Skill {
|
|||||||
return modifiers.containsKey(path);
|
return modifiers.containsKey(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
@Override
|
@Override
|
||||||
public boolean getResult(SkillMetadata meta) {
|
public boolean getResult(SkillMetadata meta) {
|
||||||
|
|
||||||
|
@ -98,6 +98,14 @@ lore-format:
|
|||||||
- '#repair-percent#'
|
- '#repair-percent#'
|
||||||
- '#item-cooldown#'
|
- '#item-cooldown#'
|
||||||
- '#additional-experience#'
|
- '#additional-experience#'
|
||||||
|
- '#additional-experience-alchemy#'
|
||||||
|
- '#additional-experience-enchanting#'
|
||||||
|
- '#additional-experience-farming#'
|
||||||
|
- '#additional-experience-fishing#'
|
||||||
|
- '#additional-experience-mining#'
|
||||||
|
- '#additional-experience-smelting#'
|
||||||
|
- '#additional-experience-smithing#'
|
||||||
|
- '#additional-experience-woodcutting#'
|
||||||
- '#cooldown-reduction#'
|
- '#cooldown-reduction#'
|
||||||
- '#mana-cost#'
|
- '#mana-cost#'
|
||||||
- '#stamina-cost#'
|
- '#stamina-cost#'
|
||||||
|
@ -64,6 +64,14 @@ max-stamina: '&3 &7■ Max Stamina: &f<plus>#'
|
|||||||
stamina-regeneration: '&3 &7■ Stamina Regeneration: &f<plus>#'
|
stamina-regeneration: '&3 &7■ Stamina Regeneration: &f<plus>#'
|
||||||
cooldown-reduction: '&3 &7■ Skill Cooldown Reduction: &f<plus>#%'
|
cooldown-reduction: '&3 &7■ Skill Cooldown Reduction: &f<plus>#%'
|
||||||
additional-experience: '&3 &7■ Additional Experience: &f<plus>#%'
|
additional-experience: '&3 &7■ Additional Experience: &f<plus>#%'
|
||||||
|
additional-experience-alchemy: '&7■ Additional Alchemy Experience: &f<plus>#%'
|
||||||
|
additional-experience-enchanting: '&7■ Additional Enchanting Experience: &f<plus>#%'
|
||||||
|
additional-experience-farming: '&7■ Additional Farming Experience: &f<plus>#%'
|
||||||
|
additional-experience-fishing: '&7■ Additional Fishing Experience: &f<plus>#%'
|
||||||
|
additional-experience-mining: '&7■ Additional Mining Experience: &f<plus>#%'
|
||||||
|
additional-experience-smelting: '&7■ Additional Smelting Experience: &f<plus>#%'
|
||||||
|
additional-experience-smithing: '&7■ Additional Smithing Experience: &f<plus>#%'
|
||||||
|
additional-experience-woodcutting: '&7■ Additional Woodcutting Experience: &f<plus>#%'
|
||||||
|
|
||||||
# Extra Options
|
# Extra Options
|
||||||
perm-effect: '&3 &7■ Permanent &f#'
|
perm-effect: '&3 &7■ Permanent &f#'
|
||||||
|
Loading…
Reference in New Issue
Block a user