mirror of
https://gitlab.com/phoenix-dvpmt/mmoitems.git
synced 2024-12-23 04:47:34 +01:00
Fixed vanilla bow/trident damage
This commit is contained in:
parent
90dc0bfa9c
commit
97e50b5dc6
@ -271,17 +271,22 @@ public class ItemUse implements Listener {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This handler listens to ALL bow shootings, including both
|
||||
* custom bows from MMOItems AND vanilla bows, since MMOItems needs to
|
||||
* apply on-hit effects like crits, elemental damage... even if the
|
||||
* player is using a vanilla bow.
|
||||
* <p>
|
||||
* Fixing commit 4aec1433
|
||||
*/
|
||||
@EventHandler
|
||||
public void handleCustomBows(EntityShootBowEvent event) {
|
||||
if (!(event.getProjectile() instanceof Arrow) || !(event.getEntity() instanceof Player))
|
||||
return;
|
||||
|
||||
NBTItem item = NBTItem.get(event.getBow());
|
||||
if (!item.hasType())
|
||||
return;
|
||||
Type type = Type.get(item.getType());
|
||||
|
||||
|
||||
PlayerData playerData = PlayerData.get((Player) event.getEntity());
|
||||
if (type != null) {
|
||||
Weapon weapon = new Weapon(playerData, item);
|
||||
|
@ -144,6 +144,14 @@ public class PlayerListener implements Listener {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* This handler listens to ALL trident shootings, including both
|
||||
* custom tridents from MMOItems AND vanilla tridents, since MMOItems
|
||||
* needs to apply on-hit effects like crits, elemental damage... even
|
||||
* if the player is using a vanilla trident.
|
||||
* <p>
|
||||
* Fixing commit 6cf6f741
|
||||
*/
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void registerTridents(ProjectileLaunchEvent event) {
|
||||
if (!(event.getEntity() instanceof Trident) || !(event.getEntity().getShooter() instanceof Player))
|
||||
@ -154,9 +162,6 @@ public class PlayerListener implements Listener {
|
||||
return;
|
||||
|
||||
NBTItem nbtItem = MythicLib.plugin.getVersion().getWrapper().getNBTItem(item.getItem());
|
||||
if (!nbtItem.hasType())
|
||||
return;
|
||||
|
||||
Type type = Type.get(nbtItem.getType());
|
||||
PlayerData playerData = PlayerData.get((Player) event.getEntity().getShooter());
|
||||
|
||||
|
@ -27,127 +27,134 @@ import java.util.WeakHashMap;
|
||||
|
||||
public class EntityManager implements Listener {
|
||||
|
||||
/**
|
||||
* Entity data used by abilities or staff attacks that utilize entities like
|
||||
* evoker fangs or shulker missiles. It can correspond to the damage the
|
||||
* entity is supposed to deal, etc
|
||||
*/
|
||||
private final Map<Integer, EntityData> entities = new HashMap<>();
|
||||
/**
|
||||
* Entity data used by abilities or staff attacks that utilize entities like
|
||||
* evoker fangs or shulker missiles. It can correspond to the damage the
|
||||
* entity is supposed to deal, etc
|
||||
*/
|
||||
private final Map<Integer, EntityData> entities = new HashMap<>();
|
||||
|
||||
private final WeakHashMap<Integer, ProjectileData> projectiles = new WeakHashMap<>();
|
||||
private final WeakHashMap<Integer, ProjectileData> projectiles = new WeakHashMap<>();
|
||||
|
||||
public void registerCustomProjectile(NBTItem sourceItem, StatMap.CachedStatMap stats, Entity entity, boolean customWeapon) {
|
||||
registerCustomProjectile(sourceItem, stats, entity, customWeapon, 1);
|
||||
}
|
||||
public void registerCustomProjectile(NBTItem sourceItem, StatMap.CachedStatMap stats, Entity entity, boolean customWeapon) {
|
||||
registerCustomProjectile(sourceItem, stats, entity, customWeapon, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a custom projectile
|
||||
*
|
||||
* @param sourceItem Item used to shoot the projectile
|
||||
* @param stats Cached stats of the player shooting the projectile
|
||||
* @param entity The custom entity
|
||||
* @param customWeapon Is the source weapon is a custom item
|
||||
* @param damageCoefficient The damage coefficient. For bows, this is basically the pull force.
|
||||
* For tridents or anything else this is always set to 1
|
||||
*/
|
||||
public void registerCustomProjectile(NBTItem sourceItem, StatMap.CachedStatMap stats, Entity entity, boolean customWeapon, double damageCoefficient) {
|
||||
/**
|
||||
* Registers a custom projectile. This is used for bows, crossbows and tridents.
|
||||
* <p>
|
||||
* Default bow/trident damage is set to 7 just like vanilla Minecraft.
|
||||
*
|
||||
* @param sourceItem Item used to shoot the projectile
|
||||
* @param stats Cached stats of the player shooting the projectile
|
||||
* @param entity The custom entity
|
||||
* @param customWeapon Is the source weapon is a custom item
|
||||
* @param damageMultiplicator The damage coefficient. For bows, this is basically the pull force.
|
||||
* For tridents or anything else this is always set to 1
|
||||
*/
|
||||
public void registerCustomProjectile(NBTItem sourceItem, StatMap.CachedStatMap stats, Entity entity, boolean customWeapon, double damageMultiplicator) {
|
||||
|
||||
/*
|
||||
* By default damage is set to minecraft's default 7. It is then
|
||||
* multiplied by the coefficient proportionnal to the pull force.
|
||||
* 1 corresponds to a fully pulled bow just like in vanilla MC.
|
||||
*
|
||||
* For tridents or crossbows, damage coefficient is always 1
|
||||
*/
|
||||
double damage = stats.getStat("ATTACK_DAMAGE");
|
||||
damage = damage == 0 ? 7 : damage * damageCoefficient;
|
||||
ItemAttackMetadata attackMeta = new ItemAttackMetadata(new DamageMetadata(damage, DamageType.WEAPON, DamageType.PHYSICAL, DamageType.PROJECTILE), stats);
|
||||
stats.setStat("ATTACK_DAMAGE", damage);
|
||||
/*
|
||||
* For bows, MC default value is 7. When using custom bows, the attack
|
||||
* damage stats returns the correct amount of damage. When using a vanilla
|
||||
* bow, attack damage is set to 1 because it's the default fist damage value.
|
||||
* Therefore MMOItems adds 6 to match the vanilla bow damage which is 7.
|
||||
*
|
||||
* Damage coefficient is how much you pull the bow. It's something between 0
|
||||
* and 1 for bows, and it's always 1 for tridents or crossbows.
|
||||
*/
|
||||
double damage = stats.getStat("ATTACK_DAMAGE");
|
||||
damage = (customWeapon ? damage : 6 + damage) * damageMultiplicator;
|
||||
|
||||
/*
|
||||
* Load arrow particles if the entity is an arrow and if the item has
|
||||
* arrow particles. Currently projectiles are only arrows so there is no
|
||||
* problem with other projectiles like snowballs etc.
|
||||
*/
|
||||
if (entity instanceof Arrow && sourceItem.hasTag("MMOITEMS_ARROW_PARTICLES"))
|
||||
new ArrowParticles((Arrow) entity, sourceItem);
|
||||
ItemAttackMetadata attackMeta = new ItemAttackMetadata(new DamageMetadata(damage, DamageType.WEAPON, DamageType.PHYSICAL, DamageType.PROJECTILE), stats);
|
||||
stats.setStat("ATTACK_DAMAGE", damage);
|
||||
|
||||
projectiles.put(entity.getEntityId(), new ProjectileData(sourceItem, attackMeta, customWeapon));
|
||||
}
|
||||
/*
|
||||
* Load arrow particles if the entity is an arrow and if the item has
|
||||
* arrow particles. Currently projectiles are only arrows so there is no
|
||||
* problem with other projectiles like snowballs etc.
|
||||
*/
|
||||
if (entity instanceof Arrow && sourceItem.hasTag("MMOITEMS_ARROW_PARTICLES"))
|
||||
new ArrowParticles((Arrow) entity, sourceItem);
|
||||
|
||||
public void registerCustomEntity(Entity entity, EntityData data) {
|
||||
entities.put(entity.getEntityId(), data);
|
||||
}
|
||||
projectiles.put(entity.getEntityId(), new ProjectileData(sourceItem, attackMeta, customWeapon));
|
||||
}
|
||||
|
||||
public boolean isCustomProjectile(Projectile projectile) {
|
||||
return projectiles.containsKey(projectile.getEntityId());
|
||||
}
|
||||
public void registerCustomEntity(Entity entity, EntityData data) {
|
||||
entities.put(entity.getEntityId(), data);
|
||||
}
|
||||
|
||||
public boolean isCustomEntity(Entity entity) {
|
||||
return entities.containsKey(entity.getEntityId());
|
||||
}
|
||||
public boolean isCustomProjectile(Projectile projectile) {
|
||||
return projectiles.containsKey(projectile.getEntityId());
|
||||
}
|
||||
|
||||
public ProjectileData getProjectileData(Projectile projectile) {
|
||||
return projectiles.get(projectile.getEntityId());
|
||||
}
|
||||
public boolean isCustomEntity(Entity entity) {
|
||||
return entities.containsKey(entity.getEntityId());
|
||||
}
|
||||
|
||||
public EntityData getEntityData(Entity entity) {
|
||||
return entities.get(entity.getEntityId());
|
||||
}
|
||||
public ProjectileData getProjectileData(Projectile projectile) {
|
||||
return projectiles.get(projectile.getEntityId());
|
||||
}
|
||||
|
||||
public void unregisterCustomProjectile(Projectile projectile) {
|
||||
projectiles.remove(projectile.getEntityId());
|
||||
}
|
||||
public EntityData getEntityData(Entity entity) {
|
||||
return entities.get(entity.getEntityId());
|
||||
}
|
||||
|
||||
public void unregisterCustomEntity(Entity entity) {
|
||||
entities.remove(entity.getEntityId());
|
||||
}
|
||||
public void unregisterCustomProjectile(Projectile projectile) {
|
||||
projectiles.remove(projectile.getEntityId());
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void a(EntityDeathEvent event) {
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(MMOItems.plugin, () -> unregisterCustomEntity(event.getEntity()));
|
||||
}
|
||||
public void unregisterCustomEntity(Entity entity) {
|
||||
entities.remove(entity.getEntityId());
|
||||
}
|
||||
|
||||
/*
|
||||
* Projectile Damage and Effects
|
||||
*
|
||||
* TODO when throwing a trident, on hit abilities dont cast half
|
||||
* of the time because you don't hold the item anymore, therefore
|
||||
* the ability does not register.
|
||||
* To fix that, not only cache the player statistics using CachedStats
|
||||
* but also the player abilities as well as elemental stats. In fact
|
||||
* a lot of extra stats need to be cached when a ranged attack is delivered.
|
||||
*
|
||||
* TODO This bug could also be exploited using a bow, by holding another item
|
||||
* after shooting an arrow!!
|
||||
*/
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void b(EntityDamageByEntityEvent event) {
|
||||
if (!(event.getDamager() instanceof Projectile) || !(event.getEntity() instanceof LivingEntity) || event.getEntity().hasMetadata("NPC"))
|
||||
return;
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void a(EntityDeathEvent event) {
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(MMOItems.plugin, () -> unregisterCustomEntity(event.getEntity()));
|
||||
}
|
||||
|
||||
Projectile projectile = (Projectile) event.getDamager();
|
||||
if (!isCustomProjectile(projectile))
|
||||
return;
|
||||
/*
|
||||
* Projectile Damage and Effects
|
||||
*
|
||||
* TODO
|
||||
* When throwing a trident, on hit abilities dont cast half
|
||||
* of the time because you don't hold the item anymore, therefore
|
||||
* the ability does not register.
|
||||
* To fix that, not only cache the player statistics using CachedStats
|
||||
* but also the player abilities as well as elemental stats. In fact
|
||||
* a lot of extra stats need to be cached when a ranged attack is delivered.
|
||||
*
|
||||
* TODO
|
||||
* This bug could also be exploited using a bow, by holding another item
|
||||
* after shooting an arrow!!
|
||||
*/
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void b(EntityDamageByEntityEvent event) {
|
||||
if (!(event.getDamager() instanceof Projectile) || !(event.getEntity() instanceof LivingEntity) || event.getEntity().hasMetadata("NPC"))
|
||||
return;
|
||||
|
||||
ProjectileData data = getProjectileData(projectile);
|
||||
LivingEntity target = (LivingEntity) event.getEntity();
|
||||
Projectile projectile = (Projectile) event.getDamager();
|
||||
if (!isCustomProjectile(projectile))
|
||||
return;
|
||||
|
||||
// Apply on hit effects
|
||||
data.getAttackMetadata().applyOnHitEffects(target);
|
||||
ProjectileData data = getProjectileData(projectile);
|
||||
LivingEntity target = (LivingEntity) event.getEntity();
|
||||
|
||||
// Apply power vanilla enchant
|
||||
if (projectile instanceof Arrow && data.getSourceItem().getItem().hasItemMeta()
|
||||
&& data.getSourceItem().getItem().getItemMeta().getEnchants().containsKey(Enchantment.ARROW_DAMAGE))
|
||||
data.getAttackMetadata().getDamage().multiply(1.25 + (.25 * data.getSourceItem().getItem().getItemMeta().getEnchantLevel(Enchantment.ARROW_DAMAGE)), DamageType.WEAPON);
|
||||
// Apply on hit effects
|
||||
data.getAttackMetadata().applyOnHitEffects(target);
|
||||
|
||||
// Apply MMOItems specific modifications
|
||||
if (data.isCustomWeapon()) {
|
||||
data.applyPotionEffects(target);
|
||||
data.getAttackMetadata().applyElementalEffects(data.getSourceItem(), target);
|
||||
}
|
||||
// Apply power vanilla enchant
|
||||
if (projectile instanceof Arrow && data.getSourceItem().getItem().hasItemMeta()
|
||||
&& data.getSourceItem().getItem().getItemMeta().getEnchants().containsKey(Enchantment.ARROW_DAMAGE))
|
||||
data.getAttackMetadata().getDamage().multiply(1.25 + (.25 * data.getSourceItem().getItem().getItemMeta().getEnchantLevel(Enchantment.ARROW_DAMAGE)), DamageType.WEAPON);
|
||||
|
||||
event.setDamage(data.getAttackMetadata().getDamage().getDamage());
|
||||
unregisterCustomProjectile(projectile);
|
||||
}
|
||||
// Apply MMOItems specific modifications
|
||||
if (data.isCustomWeapon()) {
|
||||
data.applyPotionEffects(target);
|
||||
data.getAttackMetadata().applyElementalEffects(data.getSourceItem(), target);
|
||||
}
|
||||
|
||||
event.setDamage(data.getAttackMetadata().getDamage().getDamage());
|
||||
unregisterCustomProjectile(projectile);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user