mirror of
https://gitlab.com/phoenix-dvpmt/mmoitems.git
synced 2025-02-28 15:41:04 +01:00
attackMetadata slight changes ; better support for MM skill conditions
This commit is contained in:
parent
6e2fb4c19d
commit
3b8540b40d
@ -20,14 +20,12 @@ public class ItemAttackMetadata extends AttackMetadata {
|
||||
super(damage, damager);
|
||||
}
|
||||
|
||||
public PlayerData getPlayerData() {
|
||||
return PlayerData.get(getDamager().getUniqueId());
|
||||
public ItemAttackMetadata(AttackMetadata attackMeta) {
|
||||
super(attackMeta.getDamage(), attackMeta.getStats());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemAttackMetadata setSuccessful(boolean successful) {
|
||||
super.setSuccessful(successful);
|
||||
return this;
|
||||
public PlayerData getPlayerData() {
|
||||
return PlayerData.get(getDamager().getUniqueId());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2,10 +2,12 @@ package net.Indyuce.mmoitems.api;
|
||||
|
||||
import io.lumine.mythic.lib.api.stat.modifier.ModifierSource;
|
||||
import io.lumine.mythic.lib.comp.target.InteractionType;
|
||||
import io.lumine.mythic.lib.damage.AttackMetadata;
|
||||
import io.lumine.mythic.lib.version.VersionSound;
|
||||
import net.Indyuce.mmoitems.MMOItems;
|
||||
import net.Indyuce.mmoitems.MMOUtils;
|
||||
import net.Indyuce.mmoitems.api.interaction.weapon.Weapon;
|
||||
import net.Indyuce.mmoitems.api.player.PlayerData;
|
||||
import net.Indyuce.mmoitems.api.player.PlayerData.CooldownType;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Particle;
|
||||
@ -19,163 +21,163 @@ import java.util.Random;
|
||||
|
||||
public enum TypeSet {
|
||||
|
||||
/**
|
||||
* Slashing weapons deal damage in a cone behind the player's initial
|
||||
* target, which makes it a deadly AoE weapon for warriors
|
||||
*/
|
||||
SLASHING(ModifierSource.MELEE_WEAPON, (attack, target, weapon) -> {
|
||||
if (!MMOItems.plugin.getConfig().getBoolean("item-ability.slashing.enabled") || attack.getPlayerData().isOnCooldown(CooldownType.SET_TYPE_ATTACK))
|
||||
return;
|
||||
/**
|
||||
* Slashing weapons deal damage in a cone behind the player's initial
|
||||
* target, which makes it a deadly AoE weapon for warriors
|
||||
*/
|
||||
SLASHING(ModifierSource.MELEE_WEAPON, (attack, damager, target, weapon) -> {
|
||||
if (!MMOItems.plugin.getConfig().getBoolean("item-ability.slashing.enabled") || damager.isOnCooldown(CooldownType.SET_TYPE_ATTACK))
|
||||
return;
|
||||
|
||||
attack.getPlayerData().applyCooldown(CooldownType.SET_TYPE_ATTACK, MMOItems.plugin.getConfig().getDouble("item-ability.slashing.cooldown"));
|
||||
Location loc = attack.getDamager().getLocation().clone().add(0, 1.3, 0);
|
||||
damager.applyCooldown(CooldownType.SET_TYPE_ATTACK, MMOItems.plugin.getConfig().getDouble("item-ability.slashing.cooldown"));
|
||||
Location loc = attack.getDamager().getLocation().clone().add(0, 1.3, 0);
|
||||
|
||||
final double a1 = (loc.getYaw() + 90) / 180 * Math.PI, p = -loc.getPitch() / 180 * Math.PI;
|
||||
for (double r = 1; r < 5; r += .3)
|
||||
for (double a = -Math.PI / 6; a < Math.PI / 6; a += Math.PI / 8 / r)
|
||||
loc.getWorld().spawnParticle(Particle.CRIT, loc.clone().add(Math.cos(a + a1) * r, Math.sin(p) * r, Math.sin(a + a1) * r), 0);
|
||||
final double a1 = (loc.getYaw() + 90) / 180 * Math.PI, p = -loc.getPitch() / 180 * Math.PI;
|
||||
for (double r = 1; r < 5; r += .3)
|
||||
for (double a = -Math.PI / 6; a < Math.PI / 6; a += Math.PI / 8 / r)
|
||||
loc.getWorld().spawnParticle(Particle.CRIT, loc.clone().add(Math.cos(a + a1) * r, Math.sin(p) * r, Math.sin(a + a1) * r), 0);
|
||||
|
||||
for (Entity entity : MMOUtils.getNearbyChunkEntities(loc))
|
||||
if (entity.getLocation().distanceSquared(loc) < 40
|
||||
&& attack.getDamager().getEyeLocation().getDirection()
|
||||
.angle(entity.getLocation().subtract(attack.getDamager().getLocation()).toVector()) < Math.PI / 3
|
||||
&& MMOUtils.canTarget(attack.getDamager(), entity, InteractionType.OFFENSE_ACTION) && !entity.equals(target)) {
|
||||
ItemAttackMetadata subAttack = new ItemAttackMetadata(attack.getDamage().clone(), attack.getStats());
|
||||
subAttack.getDamage().multiply(.4);
|
||||
subAttack.applyEffectsAndDamage(weapon.getNBTItem(), (LivingEntity) entity);
|
||||
}
|
||||
}),
|
||||
for (Entity entity : MMOUtils.getNearbyChunkEntities(loc))
|
||||
if (entity.getLocation().distanceSquared(loc) < 40
|
||||
&& attack.getDamager().getEyeLocation().getDirection()
|
||||
.angle(entity.getLocation().subtract(attack.getDamager().getLocation()).toVector()) < Math.PI / 3
|
||||
&& MMOUtils.canTarget(attack.getDamager(), entity, InteractionType.OFFENSE_ACTION) && !entity.equals(target)) {
|
||||
ItemAttackMetadata subAttack = new ItemAttackMetadata(attack.getDamage().clone(), attack.getStats());
|
||||
subAttack.getDamage().multiply(.4);
|
||||
subAttack.applyEffectsAndDamage(weapon.getNBTItem(), (LivingEntity) entity);
|
||||
}
|
||||
}),
|
||||
|
||||
/**
|
||||
* Piercing weapons deal damage in a line behind the initial target, which
|
||||
* is harder to land than a slashing weapon but the AoE damage ratio is
|
||||
* increased which makes it a perfect 'double or nothing' weapon for
|
||||
* assassins
|
||||
*/
|
||||
PIERCING(ModifierSource.MELEE_WEAPON, (attack, target, weapon) -> {
|
||||
if (!MMOItems.plugin.getConfig().getBoolean("item-ability.piercing.enabled") || attack.getPlayerData().isOnCooldown(CooldownType.SET_TYPE_ATTACK))
|
||||
return;
|
||||
/**
|
||||
* Piercing weapons deal damage in a line behind the initial target, which
|
||||
* is harder to land than a slashing weapon but the AoE damage ratio is
|
||||
* increased which makes it a perfect 'double or nothing' weapon for
|
||||
* assassins
|
||||
*/
|
||||
PIERCING(ModifierSource.MELEE_WEAPON, (attack, damager, target, weapon) -> {
|
||||
if (!MMOItems.plugin.getConfig().getBoolean("item-ability.piercing.enabled") || damager.isOnCooldown(CooldownType.SET_TYPE_ATTACK))
|
||||
return;
|
||||
|
||||
attack.getPlayerData().applyCooldown(CooldownType.SET_TYPE_ATTACK, MMOItems.plugin.getConfig().getDouble("item-ability.piercing.cooldown"));
|
||||
Location loc = attack.getDamager().getLocation().clone().add(0, 1.3, 0);
|
||||
damager.applyCooldown(CooldownType.SET_TYPE_ATTACK, MMOItems.plugin.getConfig().getDouble("item-ability.piercing.cooldown"));
|
||||
Location loc = attack.getDamager().getLocation().clone().add(0, 1.3, 0);
|
||||
|
||||
final double a1 = (loc.getYaw() + 90) / 180 * Math.PI, p = -loc.getPitch() / 180 * Math.PI;
|
||||
for (double r = 1; r < 5; r += .3)
|
||||
for (double a = -Math.PI / 12; a < Math.PI / 12; a += Math.PI / 16 / r)
|
||||
loc.getWorld().spawnParticle(Particle.CRIT, loc.clone().add(Math.cos(a + a1) * r, Math.sin(p) * r, Math.sin(a + a1) * r), 0);
|
||||
final double a1 = (loc.getYaw() + 90) / 180 * Math.PI, p = -loc.getPitch() / 180 * Math.PI;
|
||||
for (double r = 1; r < 5; r += .3)
|
||||
for (double a = -Math.PI / 12; a < Math.PI / 12; a += Math.PI / 16 / r)
|
||||
loc.getWorld().spawnParticle(Particle.CRIT, loc.clone().add(Math.cos(a + a1) * r, Math.sin(p) * r, Math.sin(a + a1) * r), 0);
|
||||
|
||||
for (Entity entity : MMOUtils.getNearbyChunkEntities(loc))
|
||||
if (entity.getLocation().distanceSquared(attack.getDamager().getLocation()) < 40
|
||||
&& attack.getDamager().getEyeLocation().getDirection()
|
||||
.angle(entity.getLocation().toVector().subtract(attack.getDamager().getLocation().toVector())) < Math.PI / 18
|
||||
&& MMOUtils.canTarget(attack.getDamager(), entity, InteractionType.OFFENSE_ACTION) && !entity.equals(target)) {
|
||||
ItemAttackMetadata subAttack = new ItemAttackMetadata(attack.getDamage().clone(), attack.getStats());
|
||||
subAttack.getDamage().multiply(.4);
|
||||
subAttack.applyEffectsAndDamage(weapon.getNBTItem(), (LivingEntity) entity);
|
||||
}
|
||||
}),
|
||||
for (Entity entity : MMOUtils.getNearbyChunkEntities(loc))
|
||||
if (entity.getLocation().distanceSquared(attack.getDamager().getLocation()) < 40
|
||||
&& attack.getDamager().getEyeLocation().getDirection()
|
||||
.angle(entity.getLocation().toVector().subtract(attack.getDamager().getLocation().toVector())) < Math.PI / 18
|
||||
&& MMOUtils.canTarget(attack.getDamager(), entity, InteractionType.OFFENSE_ACTION) && !entity.equals(target)) {
|
||||
ItemAttackMetadata subAttack = new ItemAttackMetadata(attack.getDamage().clone(), attack.getStats());
|
||||
subAttack.getDamage().multiply(.4);
|
||||
subAttack.applyEffectsAndDamage(weapon.getNBTItem(), (LivingEntity) entity);
|
||||
}
|
||||
}),
|
||||
|
||||
/**
|
||||
* Blunt weapons are like 1.9 sweep attacks. They damage all enemies nearby
|
||||
* and apply a slight knockback
|
||||
*/
|
||||
BLUNT(ModifierSource.MELEE_WEAPON, (attack, target, weapon) -> {
|
||||
final Random random = new Random();
|
||||
float pitchRange = 0.7f + random.nextFloat() * (0.9f - 0.7f);
|
||||
/**
|
||||
* Blunt weapons are like 1.9 sweep attacks. They damage all enemies nearby
|
||||
* and apply a slight knockback
|
||||
*/
|
||||
BLUNT(ModifierSource.MELEE_WEAPON, (attack, damager, target, weapon) -> {
|
||||
final Random random = new Random();
|
||||
float pitchRange = 0.7f + random.nextFloat() * (0.9f - 0.7f);
|
||||
|
||||
if (MMOItems.plugin.getConfig().getBoolean("item-ability.blunt.aoe.enabled")
|
||||
&& !attack.getPlayerData().isOnCooldown(CooldownType.SPECIAL_ATTACK)) {
|
||||
if (MMOItems.plugin.getConfig().getBoolean("item-ability.blunt.aoe.enabled")
|
||||
&& !damager.isOnCooldown(CooldownType.SPECIAL_ATTACK)) {
|
||||
|
||||
attack.getPlayerData().applyCooldown(CooldownType.SPECIAL_ATTACK, MMOItems.plugin.getConfig().getDouble("item-ability.blunt.aoe.cooldown"));
|
||||
target.getWorld().playSound(target.getLocation(), Sound.BLOCK_ANVIL_LAND, 0.6f, pitchRange);
|
||||
target.getWorld().spawnParticle(Particle.EXPLOSION_LARGE, target.getLocation().add(0, 1, 0), 0);
|
||||
double bluntPower = attack.getStats().getStat("BLUNT_POWER");
|
||||
if (bluntPower > 0) {
|
||||
double bluntRating = weapon.getValue(attack.getStats().getStat("BLUNT_RATING"),
|
||||
MMOItems.plugin.getConfig().getDouble("default.blunt-rating")) / 100;
|
||||
for (Entity entity : target.getNearbyEntities(bluntPower, bluntPower, bluntPower))
|
||||
if (MMOUtils.canTarget(attack.getDamager(), entity, InteractionType.OFFENSE_ACTION) && !entity.equals(target)) {
|
||||
ItemAttackMetadata subAttack = new ItemAttackMetadata(attack.getDamage().clone(), attack.getStats());
|
||||
subAttack.getDamage().multiply(bluntRating);
|
||||
subAttack.applyEffectsAndDamage(weapon.getNBTItem(), (LivingEntity) entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
damager.applyCooldown(CooldownType.SPECIAL_ATTACK, MMOItems.plugin.getConfig().getDouble("item-ability.blunt.aoe.cooldown"));
|
||||
target.getWorld().playSound(target.getLocation(), Sound.BLOCK_ANVIL_LAND, 0.6f, pitchRange);
|
||||
target.getWorld().spawnParticle(Particle.EXPLOSION_LARGE, target.getLocation().add(0, 1, 0), 0);
|
||||
double bluntPower = attack.getStats().getStat("BLUNT_POWER");
|
||||
if (bluntPower > 0) {
|
||||
double bluntRating = weapon.getValue(attack.getStats().getStat("BLUNT_RATING"),
|
||||
MMOItems.plugin.getConfig().getDouble("default.blunt-rating")) / 100;
|
||||
for (Entity entity : target.getNearbyEntities(bluntPower, bluntPower, bluntPower))
|
||||
if (MMOUtils.canTarget(attack.getDamager(), entity, InteractionType.OFFENSE_ACTION) && !entity.equals(target)) {
|
||||
ItemAttackMetadata subAttack = new ItemAttackMetadata(attack.getDamage().clone(), attack.getStats());
|
||||
subAttack.getDamage().multiply(bluntRating);
|
||||
subAttack.applyEffectsAndDamage(weapon.getNBTItem(), (LivingEntity) entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (MMOItems.plugin.getConfig().getBoolean("item-ability.blunt.stun.enabled")
|
||||
&& !attack.getPlayerData().isOnCooldown(CooldownType.SPECIAL_ATTACK)
|
||||
&& random.nextDouble() < MMOItems.plugin.getConfig().getDouble("item-ability.blunt.stun.chance") / 100) {
|
||||
if (MMOItems.plugin.getConfig().getBoolean("item-ability.blunt.stun.enabled")
|
||||
&& !damager.isOnCooldown(CooldownType.SPECIAL_ATTACK)
|
||||
&& random.nextDouble() < MMOItems.plugin.getConfig().getDouble("item-ability.blunt.stun.chance") / 100) {
|
||||
|
||||
attack.getPlayerData().applyCooldown(CooldownType.SPECIAL_ATTACK, MMOItems.plugin.getConfig().getDouble("item-ability.blunt.stun.cooldown"));
|
||||
target.getWorld().playSound(target.getLocation(), VersionSound.ENTITY_ZOMBIE_ATTACK_WOODEN_DOOR.toSound(), 1, 2);
|
||||
target.removePotionEffect(PotionEffectType.SLOW);
|
||||
target.removePotionEffect(PotionEffectType.BLINDNESS);
|
||||
target.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, 20, 0));
|
||||
target.addPotionEffect(
|
||||
new PotionEffect(PotionEffectType.SLOW, (int) (30 * MMOItems.plugin.getConfig().getDouble("item-ability.blunt.stun.power")), 1));
|
||||
Location loc = target.getLocation();
|
||||
loc.setYaw((float) (loc.getYaw() + 2 * (random.nextDouble() - .5) * 90));
|
||||
loc.setPitch((float) (loc.getPitch() + 2 * (random.nextDouble() - .5) * 30));
|
||||
}
|
||||
}),
|
||||
damager.applyCooldown(CooldownType.SPECIAL_ATTACK, MMOItems.plugin.getConfig().getDouble("item-ability.blunt.stun.cooldown"));
|
||||
target.getWorld().playSound(target.getLocation(), VersionSound.ENTITY_ZOMBIE_ATTACK_WOODEN_DOOR.toSound(), 1, 2);
|
||||
target.removePotionEffect(PotionEffectType.SLOW);
|
||||
target.removePotionEffect(PotionEffectType.BLINDNESS);
|
||||
target.addPotionEffect(new PotionEffect(PotionEffectType.BLINDNESS, 20, 0));
|
||||
target.addPotionEffect(
|
||||
new PotionEffect(PotionEffectType.SLOW, (int) (30 * MMOItems.plugin.getConfig().getDouble("item-ability.blunt.stun.power")), 1));
|
||||
Location loc = target.getLocation();
|
||||
loc.setYaw((float) (loc.getYaw() + 2 * (random.nextDouble() - .5) * 90));
|
||||
loc.setPitch((float) (loc.getPitch() + 2 * (random.nextDouble() - .5) * 30));
|
||||
}
|
||||
}),
|
||||
|
||||
/**
|
||||
* Any item type can may apply their stats even when worn in offhand.
|
||||
* They're the only items with that specific property
|
||||
*/
|
||||
OFFHAND(ModifierSource.OTHER),
|
||||
/**
|
||||
* Any item type can may apply their stats even when worn in offhand.
|
||||
* They're the only items with that specific property
|
||||
*/
|
||||
OFFHAND(ModifierSource.OTHER),
|
||||
|
||||
/**
|
||||
* Ranged attacks based weapons. when the player is too squishy to fight in
|
||||
* the middle of the battle-field, these weapons allow him to take some
|
||||
* distance and still deal some good damage
|
||||
*/
|
||||
RANGE(ModifierSource.RANGED_WEAPON),
|
||||
/**
|
||||
* Ranged attacks based weapons. when the player is too squishy to fight in
|
||||
* the middle of the battle-field, these weapons allow him to take some
|
||||
* distance and still deal some good damage
|
||||
*/
|
||||
RANGE(ModifierSource.RANGED_WEAPON),
|
||||
|
||||
/**
|
||||
* Any other item type, like armor, consumables, etc. They all have their
|
||||
* very specific passive depending on their item type
|
||||
*/
|
||||
EXTRA(ModifierSource.OTHER);
|
||||
/**
|
||||
* Any other item type, like armor, consumables, etc. They all have their
|
||||
* very specific passive depending on their item type
|
||||
*/
|
||||
EXTRA(ModifierSource.OTHER);
|
||||
|
||||
/**
|
||||
* Interface between MMOItems' type sets and MythicLibs' modifierSources which let
|
||||
* MythicLib know what type of item is giving some stat modifiers to a player
|
||||
*/
|
||||
private final ModifierSource modifierSource;
|
||||
/**
|
||||
* Interface between MMOItems' type sets and MythicLibs' modifierSources which let
|
||||
* MythicLib know what type of item is giving some stat modifiers to a player
|
||||
*/
|
||||
private final ModifierSource modifierSource;
|
||||
|
||||
private final SetAttackHandler<ItemAttackMetadata, LivingEntity, Weapon> attackHandler;
|
||||
private final String name;
|
||||
private final SetAttackHandler attackHandler;
|
||||
private final String name;
|
||||
|
||||
private TypeSet(ModifierSource modifierSource) {
|
||||
this(modifierSource, null);
|
||||
}
|
||||
private TypeSet(ModifierSource modifierSource) {
|
||||
this(modifierSource, null);
|
||||
}
|
||||
|
||||
private TypeSet(ModifierSource modifierSource, SetAttackHandler<ItemAttackMetadata, LivingEntity, Weapon> attackHandler) {
|
||||
this.attackHandler = attackHandler;
|
||||
this.modifierSource = modifierSource;
|
||||
private TypeSet(ModifierSource modifierSource, SetAttackHandler attackHandler) {
|
||||
this.attackHandler = attackHandler;
|
||||
this.modifierSource = modifierSource;
|
||||
|
||||
this.name = MMOUtils.caseOnWords(name().toLowerCase());
|
||||
}
|
||||
this.name = MMOUtils.caseOnWords(name().toLowerCase());
|
||||
}
|
||||
|
||||
public ModifierSource getModifierSource() {
|
||||
return modifierSource;
|
||||
}
|
||||
public ModifierSource getModifierSource() {
|
||||
return modifierSource;
|
||||
}
|
||||
|
||||
public boolean hasAttackEffect() {
|
||||
return attackHandler != null;
|
||||
}
|
||||
public boolean hasAttackEffect() {
|
||||
return attackHandler != null;
|
||||
}
|
||||
|
||||
public void applyAttackEffect(ItemAttackMetadata attackMeta, LivingEntity target, Weapon weapon) {
|
||||
attackHandler.apply(attackMeta, target, weapon);
|
||||
}
|
||||
public void applyAttackEffect(AttackMetadata attackMeta, PlayerData damager, LivingEntity target, Weapon weapon) {
|
||||
attackHandler.apply(attackMeta, damager, target, weapon);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
interface SetAttackHandler<A, B, C> {
|
||||
void apply(A a, B b, C c);
|
||||
}
|
||||
@FunctionalInterface
|
||||
interface SetAttackHandler {
|
||||
void apply(AttackMetadata attack, PlayerData damager, LivingEntity target, Weapon weapon);
|
||||
}
|
||||
}
|
||||
|
@ -3,8 +3,8 @@ package net.Indyuce.mmoitems.api.interaction.weapon;
|
||||
import io.lumine.mythic.lib.MythicLib;
|
||||
import io.lumine.mythic.lib.api.item.NBTItem;
|
||||
import io.lumine.mythic.lib.comp.flags.CustomFlag;
|
||||
import io.lumine.mythic.lib.damage.AttackMetadata;
|
||||
import net.Indyuce.mmoitems.ItemStats;
|
||||
import net.Indyuce.mmoitems.api.ItemAttackMetadata;
|
||||
import net.Indyuce.mmoitems.api.interaction.UseItem;
|
||||
import net.Indyuce.mmoitems.api.player.PlayerData;
|
||||
import net.Indyuce.mmoitems.api.player.PlayerData.CooldownType;
|
||||
@ -81,19 +81,24 @@ public class Weapon extends UseItem {
|
||||
return true;
|
||||
}
|
||||
|
||||
public ItemAttackMetadata handleTargetedAttack(ItemAttackMetadata attackMeta, LivingEntity target) {
|
||||
/**
|
||||
* @param attackMeta The attack being performed
|
||||
* @param target The attack target
|
||||
* @return If the attack is successful, or if it was canceled otherwise
|
||||
*/
|
||||
public boolean handleTargetedAttack(AttackMetadata attackMeta, LivingEntity target) {
|
||||
|
||||
// Handle weapon cooldown, mana and stamina costs
|
||||
double attackSpeed = getNBTItem().getStat(ItemStats.ATTACK_SPEED.getId());
|
||||
attackSpeed = attackSpeed == 0 ? 1.493 : 1 / attackSpeed;
|
||||
if (!applyWeaponCosts())
|
||||
return attackMeta.setSuccessful(false);
|
||||
return false;
|
||||
|
||||
// Handle item set attack effects
|
||||
if (getMMOItem().getType().getItemSet().hasAttackEffect() && !getNBTItem().getBoolean("MMOITEMS_DISABLE_ATTACK_PASSIVE"))
|
||||
getMMOItem().getType().getItemSet().applyAttackEffect(attackMeta, target, this);
|
||||
getMMOItem().getType().getItemSet().applyAttackEffect(attackMeta, playerData, target, this);
|
||||
|
||||
return attackMeta;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected Location getGround(Location loc) {
|
||||
|
@ -398,7 +398,7 @@ public class PlayerData {
|
||||
*/
|
||||
if (target == null ? !MythicLib.plugin.getFlags().isFlagAllowed(getPlayer(), CustomFlag.MMO_ABILITIES)
|
||||
: !MythicLib.plugin.getFlags().isFlagAllowed(target.getLocation(), CustomFlag.MMO_ABILITIES))
|
||||
return attack.setSuccessful(false);
|
||||
return attack;
|
||||
|
||||
for (AbilityData ability : itemAbilities)
|
||||
if (ability.getCastingMode() == castMode)
|
||||
|
@ -56,7 +56,7 @@ public class RealDualWieldHook implements Listener {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!weapon.handleTargetedAttack(attackMeta = getAttack(playerData, event), target).isSuccessful()) {
|
||||
if (!weapon.handleTargetedAttack(attackMeta = getAttack(playerData, event), target)) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package net.Indyuce.mmoitems.comp.mmocore;
|
||||
import net.Indyuce.mmocore.MMOCore;
|
||||
import net.Indyuce.mmocore.api.event.PlayerChangeClassEvent;
|
||||
import net.Indyuce.mmocore.api.event.PlayerLevelUpEvent;
|
||||
import net.Indyuce.mmocore.api.event.PlayerResourceUpdateEvent;
|
||||
import net.Indyuce.mmocore.api.player.PlayerData;
|
||||
import net.Indyuce.mmocore.api.player.attribute.PlayerAttribute;
|
||||
import net.Indyuce.mmocore.experience.Profession;
|
||||
@ -104,12 +105,12 @@ public class MMOCoreHook implements RPGHandler, Listener {
|
||||
|
||||
@Override
|
||||
public void giveMana(double value) {
|
||||
data.giveMana(value);
|
||||
data.giveMana(value, PlayerResourceUpdateEvent.UpdateReason.REGENERATION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void giveStamina(double value) {
|
||||
data.giveStamina(value);
|
||||
data.giveStamina(value, PlayerResourceUpdateEvent.UpdateReason.REGENERATION);
|
||||
}
|
||||
}
|
||||
}
|
@ -47,7 +47,11 @@ public class MythicMobsAbility extends Ability<MythicMobsAbilityMetadata> {
|
||||
|
||||
@Override
|
||||
public void whenCast(ItemAttackMetadata attackMeta, MythicMobsAbilityMetadata ability) {
|
||||
LivingEntity target = ability.getTarget();
|
||||
skill.execute(ability.getSkillMetadata());
|
||||
}
|
||||
|
||||
@Override
|
||||
public MythicMobsAbilityMetadata canBeCast(ItemAttackMetadata attackMeta, LivingEntity target, AbilityData data) {
|
||||
|
||||
// TODO what's the difference between trigger and caster.
|
||||
AbstractEntity trigger = BukkitAdapter.adapt(attackMeta.getDamager());
|
||||
@ -58,20 +62,12 @@ public class MythicMobsAbility extends Ability<MythicMobsAbilityMetadata> {
|
||||
|
||||
targetEntities.add(BukkitAdapter.adapt(target));
|
||||
|
||||
SkillMetadata data = new SkillMetadata(SkillTrigger.CAST, caster, trigger, BukkitAdapter.adapt(attackMeta.getDamager().getEyeLocation()), targetEntities, targetLocations, 1);
|
||||
SkillMetadata skillMeta = new SkillMetadata(SkillTrigger.CAST, caster, trigger, BukkitAdapter.adapt(attackMeta.getDamager().getEyeLocation()), targetEntities, targetLocations, 1);
|
||||
|
||||
// Stats are cached inside a variable
|
||||
data.getVariables().putObject("MMOStatMap", attackMeta.getStats());
|
||||
data.getVariables().putObject("MMOSkill", ability.getAbility());
|
||||
skillMeta.getVariables().putObject("MMOStatMap", attackMeta.getStats());
|
||||
skillMeta.getVariables().putObject("MMOSkill", data.getAbility());
|
||||
|
||||
if (skill.usable(data, SkillTrigger.CAST))
|
||||
skill.execute(data);
|
||||
else
|
||||
attackMeta.setSuccessful(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MythicMobsAbilityMetadata canBeCast(ItemAttackMetadata attackMeta, LivingEntity target, AbilityData data) {
|
||||
return new MythicMobsAbilityMetadata(data, target);
|
||||
return new MythicMobsAbilityMetadata(data, skill, skillMeta);
|
||||
}
|
||||
}
|
||||
|
@ -1,24 +1,28 @@
|
||||
package net.Indyuce.mmoitems.comp.mythicmobs.skill;
|
||||
|
||||
import io.lumine.xikage.mythicmobs.skills.Skill;
|
||||
import io.lumine.xikage.mythicmobs.skills.SkillMetadata;
|
||||
import io.lumine.xikage.mythicmobs.skills.SkillTrigger;
|
||||
import net.Indyuce.mmoitems.ability.AbilityMetadata;
|
||||
import net.Indyuce.mmoitems.stat.data.AbilityData;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
|
||||
public class MythicMobsAbilityMetadata extends AbilityMetadata {
|
||||
private final LivingEntity target;
|
||||
private final Skill skill;
|
||||
private final SkillMetadata skillMeta;
|
||||
|
||||
public MythicMobsAbilityMetadata(AbilityData ability, LivingEntity target) {
|
||||
public MythicMobsAbilityMetadata(AbilityData ability, Skill skill, SkillMetadata skillMeta) {
|
||||
super(ability);
|
||||
|
||||
this.target = target;
|
||||
this.skill = skill;
|
||||
this.skillMeta = skillMeta;
|
||||
}
|
||||
|
||||
public LivingEntity getTarget() {
|
||||
return target;
|
||||
public SkillMetadata getSkillMetadata() {
|
||||
return skillMeta;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSuccessful() {
|
||||
return true;
|
||||
return skill.usable(skillMeta, SkillTrigger.CAST);
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package net.Indyuce.mmoitems.listener;
|
||||
|
||||
import io.lumine.mythic.lib.MythicLib;
|
||||
import io.lumine.mythic.lib.api.event.PlayerAttackEvent;
|
||||
import io.lumine.mythic.lib.api.item.NBTItem;
|
||||
import io.lumine.mythic.lib.api.player.EquipmentSlot;
|
||||
import io.lumine.mythic.lib.api.stat.StatMap;
|
||||
@ -104,29 +105,19 @@ public class ItemUse implements Listener {
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
||||
public void meleeAttacks(EntityDamageByEntityEvent event) {
|
||||
public void meleeAttacks(PlayerAttackEvent event) {
|
||||
|
||||
/*
|
||||
* Citizens and Sentinels NPC support; damage = 0 check to ignore safety
|
||||
* checks; check for entity attack
|
||||
*/
|
||||
if (event.getDamage() == 0 || event.getCause() != DamageCause.ENTITY_ATTACK || !(event.getEntity() instanceof LivingEntity)
|
||||
|| !(event.getDamager() instanceof Player) || event.getEntity().hasMetadata("NPC") || event.getDamager().hasMetadata("NPC"))
|
||||
return;
|
||||
|
||||
// Custom damage check
|
||||
LivingEntity target = (LivingEntity) event.getEntity();
|
||||
if (MythicLib.plugin.getDamage().findInfo(target) != null)
|
||||
// Checks if the target is a damageable entity and if it's a melee attack
|
||||
if (event.getBukkitCause() != DamageCause.ENTITY_ATTACK || !(event.getEntity() instanceof LivingEntity))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Must apply attack conditions before apply any effects. the event must
|
||||
* be cancelled before anything is applied
|
||||
*/
|
||||
Player player = (Player) event.getDamager();
|
||||
Player player = event.getPlayer();
|
||||
PlayerData playerData = PlayerData.get(player);
|
||||
NBTItem item = MythicLib.plugin.getVersion().getWrapper().getNBTItem(player.getInventory().getItemInMainHand());
|
||||
ItemAttackMetadata attackMeta = null;
|
||||
|
||||
if (item.hasType() && Type.get(item.getType()) != Type.BLOCK) {
|
||||
Weapon weapon = new Weapon(playerData, item);
|
||||
@ -141,17 +132,14 @@ public class ItemUse implements Listener {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!weapon.handleTargetedAttack(attackMeta = getAttack(playerData, event), target).isSuccessful()) {
|
||||
if (!weapon.handleTargetedAttack(event.getAttack(), event.getEntity())) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Cast on-hit abilities and add the extra damage to the damage event
|
||||
(attackMeta == null ? attackMeta = getAttack(playerData, event) : attackMeta).applyEffects(item, target);
|
||||
|
||||
// Finally update Bukkit event
|
||||
event.setDamage(attackMeta.getDamage().getDamage());
|
||||
new ItemAttackMetadata(event.getAttack()).applyEffects(item, event.getEntity());
|
||||
}
|
||||
|
||||
private ItemAttackMetadata getAttack(PlayerData playerData, EntityDamageByEntityEvent event) {
|
||||
|
@ -180,9 +180,28 @@ public class PlayerListener implements Listener {
|
||||
* Fixes an issue where quickly swapping items in hand just
|
||||
* does not update the player's inventory which can make the
|
||||
* player cast abilities or attacks with not the correct stats
|
||||
*
|
||||
* @deprecated This does cost some performance and that update
|
||||
* method NEEDS some improvement in the future
|
||||
*/
|
||||
@Deprecated
|
||||
@EventHandler
|
||||
public void registerInventoryUpdates(PlayerSwapHandItemsEvent event) {
|
||||
PlayerData.get(event.getPlayer()).updateInventory();
|
||||
public void registerInventoryUpdates1(PlayerSwapHandItemsEvent event) {
|
||||
PlayerData.get(event.getPlayer()).getInventory().scheduleUpdate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixes an issue where quickly swapping items in hand just
|
||||
* does not update the player's inventory which can make the
|
||||
* player cast abilities or attacks with not the correct stats
|
||||
*
|
||||
* @deprecated This does cost some performance and that update
|
||||
* method NEEDS some improvement in the future
|
||||
*/
|
||||
@Deprecated
|
||||
@EventHandler
|
||||
public void registerInventoryUpdates2(PlayerItemHeldEvent event) {
|
||||
PlayerData.get(event.getPlayer()).getInventory().scheduleUpdate();
|
||||
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user