mirror of
https://github.com/mcMMO-Dev/mcMMO.git
synced 2024-11-24 22:26:46 +01:00
Initial work on crossbows
This commit is contained in:
parent
cf6af4630d
commit
7543d8be12
@ -17,6 +17,7 @@ Version 2.1.133
|
|||||||
Smelting now has a Bonus Drops section in config.yml
|
Smelting now has a Bonus Drops section in config.yml
|
||||||
Second Smelt now only doubles smelting results for items which have bonus drop entries in the config
|
Second Smelt now only doubles smelting results for items which have bonus drop entries in the config
|
||||||
Fixed an array out of index bug for inventory click events
|
Fixed an array out of index bug for inventory click events
|
||||||
|
mcMMO will now register arrows shot from the offhand as being from either Archery or Crossbows (before mcMMO ignored offhand Archery)
|
||||||
|
|
||||||
(These permissions are all included in the mcmmo.defaults node)
|
(These permissions are all included in the mcmmo.defaults node)
|
||||||
New permission node 'mcmmo.commands.tridents'
|
New permission node 'mcmmo.commands.tridents'
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
package com.gmail.nossr50.datatypes.meta;
|
||||||
|
|
||||||
|
import org.bukkit.metadata.FixedMetadataValue;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class ProjectileOriginMeta extends FixedMetadataValue {
|
||||||
|
/**
|
||||||
|
* Initializes a FixedMetadataValue with an Object
|
||||||
|
*
|
||||||
|
* @param owningPlugin the {@link Plugin} that created this metadata value
|
||||||
|
* @param value the value assigned to this metadata value
|
||||||
|
*/
|
||||||
|
public ProjectileOriginMeta(@NotNull Plugin owningPlugin, int value) {
|
||||||
|
super(owningPlugin, value);
|
||||||
|
}
|
||||||
|
}
|
@ -4,6 +4,7 @@ import com.gmail.nossr50.config.AdvancedConfig;
|
|||||||
import com.gmail.nossr50.config.Config;
|
import com.gmail.nossr50.config.Config;
|
||||||
import com.gmail.nossr50.config.WorldBlacklist;
|
import com.gmail.nossr50.config.WorldBlacklist;
|
||||||
import com.gmail.nossr50.config.experience.ExperienceConfig;
|
import com.gmail.nossr50.config.experience.ExperienceConfig;
|
||||||
|
import com.gmail.nossr50.datatypes.meta.ProjectileOriginMeta;
|
||||||
import com.gmail.nossr50.datatypes.player.McMMOPlayer;
|
import com.gmail.nossr50.datatypes.player.McMMOPlayer;
|
||||||
import com.gmail.nossr50.datatypes.skills.SubSkillType;
|
import com.gmail.nossr50.datatypes.skills.SubSkillType;
|
||||||
import com.gmail.nossr50.datatypes.skills.subskills.interfaces.InteractType;
|
import com.gmail.nossr50.datatypes.skills.subskills.interfaces.InteractType;
|
||||||
@ -19,6 +20,7 @@ import com.gmail.nossr50.skills.taming.Taming;
|
|||||||
import com.gmail.nossr50.skills.taming.TamingManager;
|
import com.gmail.nossr50.skills.taming.TamingManager;
|
||||||
import com.gmail.nossr50.skills.unarmed.UnarmedManager;
|
import com.gmail.nossr50.skills.unarmed.UnarmedManager;
|
||||||
import com.gmail.nossr50.util.BlockUtils;
|
import com.gmail.nossr50.util.BlockUtils;
|
||||||
|
import com.gmail.nossr50.util.ItemUtils;
|
||||||
import com.gmail.nossr50.util.Misc;
|
import com.gmail.nossr50.util.Misc;
|
||||||
import com.gmail.nossr50.util.Permissions;
|
import com.gmail.nossr50.util.Permissions;
|
||||||
import com.gmail.nossr50.util.player.NotificationManager;
|
import com.gmail.nossr50.util.player.NotificationManager;
|
||||||
@ -122,7 +124,7 @@ public class EntityListener implements Listener {
|
|||||||
projectile.setMetadata(mcMMO.arrowDistanceKey, new FixedMetadataValue(plugin, projectile.getLocation()));
|
projectile.setMetadata(mcMMO.arrowDistanceKey, new FixedMetadataValue(plugin, projectile.getLocation()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
|
||||||
public void onProjectileLaunch(ProjectileLaunchEvent event) {
|
public void onProjectileLaunch(ProjectileLaunchEvent event) {
|
||||||
/* WORLD BLACKLIST CHECK */
|
/* WORLD BLACKLIST CHECK */
|
||||||
if(WorldBlacklist.isWorldBlacklisted(event.getEntity().getWorld()))
|
if(WorldBlacklist.isWorldBlacklisted(event.getEntity().getWorld()))
|
||||||
@ -144,9 +146,19 @@ public class EntityListener implements Listener {
|
|||||||
if(!(projectile instanceof Arrow))
|
if(!(projectile instanceof Arrow))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
projectile.setMetadata(mcMMO.bowForceKey, new FixedMetadataValue(plugin, 1.0));
|
|
||||||
projectile.setMetadata(mcMMO.arrowDistanceKey, new FixedMetadataValue(plugin, projectile.getLocation()));
|
projectile.setMetadata(mcMMO.arrowDistanceKey, new FixedMetadataValue(plugin, projectile.getLocation()));
|
||||||
|
|
||||||
|
//Track origin of projectile
|
||||||
|
if(ItemUtils.hasItemInMainHand(player, "bow")) {
|
||||||
|
markProjectileOriginAsBow(projectile);
|
||||||
|
} else if(ItemUtils.hasItemInMainHand(player, "crossbow")) {
|
||||||
|
markProjectileOriginAsCrossbow(projectile);
|
||||||
|
} else if(ItemUtils.hasItemInOffHand(player, "bow")) {
|
||||||
|
markProjectileOriginAsBow(projectile);
|
||||||
|
} else if(ItemUtils.hasItemInOffHand(player, "crossbow")) {
|
||||||
|
markProjectileOriginAsCrossbow(projectile);
|
||||||
|
}
|
||||||
|
|
||||||
for(Enchantment enchantment : player.getInventory().getItemInMainHand().getEnchantments().keySet()) {
|
for(Enchantment enchantment : player.getInventory().getItemInMainHand().getEnchantments().keySet()) {
|
||||||
if(enchantment.getName().equalsIgnoreCase("piercing"))
|
if(enchantment.getName().equalsIgnoreCase("piercing"))
|
||||||
return;
|
return;
|
||||||
@ -158,6 +170,14 @@ public class EntityListener implements Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void markProjectileOriginAsCrossbow(Projectile projectile) {
|
||||||
|
projectile.setMetadata(mcMMO.PROJECTILE_ORIGIN_METAKEY, new ProjectileOriginMeta(plugin, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void markProjectileOriginAsBow(Projectile projectile) {
|
||||||
|
projectile.setMetadata(mcMMO.PROJECTILE_ORIGIN_METAKEY, new ProjectileOriginMeta(plugin, 1));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Monitor EntityChangeBlock events.
|
* Monitor EntityChangeBlock events.
|
||||||
*
|
*
|
||||||
|
@ -134,6 +134,7 @@ public class mcMMO extends JavaPlugin {
|
|||||||
public final static String greenThumbDataKey = "mcMMO: Green Thumb";
|
public final static String greenThumbDataKey = "mcMMO: Green Thumb";
|
||||||
public final static String databaseCommandKey = "mcMMO: Processing Database Command";
|
public final static String databaseCommandKey = "mcMMO: Processing Database Command";
|
||||||
public final static String bredMetadataKey = "mcMMO: Bred Animal";
|
public final static String bredMetadataKey = "mcMMO: Bred Animal";
|
||||||
|
public final static String PROJECTILE_ORIGIN_METAKEY = "mcMMO: Projectile Origin";
|
||||||
|
|
||||||
public static FixedMetadataValue metadataValue;
|
public static FixedMetadataValue metadataValue;
|
||||||
|
|
||||||
|
@ -2,10 +2,38 @@ package com.gmail.nossr50.skills.crossbows;
|
|||||||
|
|
||||||
import com.gmail.nossr50.datatypes.player.McMMOPlayer;
|
import com.gmail.nossr50.datatypes.player.McMMOPlayer;
|
||||||
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
|
import com.gmail.nossr50.datatypes.skills.PrimarySkillType;
|
||||||
|
import com.gmail.nossr50.mcMMO;
|
||||||
import com.gmail.nossr50.skills.SkillManager;
|
import com.gmail.nossr50.skills.SkillManager;
|
||||||
|
import com.gmail.nossr50.skills.archery.Archery;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.entity.Entity;
|
||||||
|
import org.bukkit.entity.LivingEntity;
|
||||||
|
|
||||||
public class CrossbowManager extends SkillManager {
|
public class CrossbowManager extends SkillManager {
|
||||||
public CrossbowManager(McMMOPlayer mcMMOPlayer) {
|
public CrossbowManager(McMMOPlayer mcMMOPlayer) {
|
||||||
super(mcMMOPlayer, PrimarySkillType.CROSSBOWS);
|
super(mcMMOPlayer, PrimarySkillType.CROSSBOWS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate bonus XP awarded for Archery when hitting a far-away target.
|
||||||
|
*
|
||||||
|
* @param target The {@link LivingEntity} damaged by the arrow
|
||||||
|
* @param damager The {@link Entity} who shot the arrow
|
||||||
|
*/
|
||||||
|
public double distanceXpBonusMultiplier(LivingEntity target, Entity damager) {
|
||||||
|
//Hacky Fix - some plugins spawn arrows and assign them to players after the ProjectileLaunchEvent fires
|
||||||
|
if(!damager.hasMetadata(mcMMO.arrowDistanceKey))
|
||||||
|
return damager.getLocation().distance(target.getLocation());
|
||||||
|
|
||||||
|
Location firedLocation = (Location) damager.getMetadata(mcMMO.arrowDistanceKey).get(0).value();
|
||||||
|
Location targetLocation = target.getLocation();
|
||||||
|
|
||||||
|
if (firedLocation.getWorld() != targetLocation.getWorld()) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: Should use its own variable
|
||||||
|
return 1 + Math.min(firedLocation.distance(targetLocation), 50) * Archery.DISTANCE_XP_MULTIPLIER;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -31,9 +31,23 @@ public final class ItemUtils {
|
|||||||
|
|
||||||
|
|
||||||
public static boolean hasItemInEitherHand(Player player, Material material) {
|
public static boolean hasItemInEitherHand(Player player, Material material) {
|
||||||
return player.getInventory().getItemInMainHand().getType() == material || player.getInventory().getItemInOffHand().getType() == material;
|
return hasItemInEitherHand(player, material.getKey().getKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean hasItemInEitherHand(Player player, String id) {
|
||||||
|
return player.getInventory().getItemInMainHand().getType().getKey().getKey().equalsIgnoreCase(id)
|
||||||
|
|| player.getInventory().getItemInOffHand().getType().getKey().getKey().equalsIgnoreCase(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean hasItemInMainHand(Player player, String id) {
|
||||||
|
return player.getInventory().getItemInMainHand().getType().getKey().getKey().equalsIgnoreCase(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean hasItemInOffHand(Player player, String id) {
|
||||||
|
return player.getInventory().getItemInOffHand().getType().getKey().getKey().equalsIgnoreCase(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the item is a sword.
|
* Checks if the item is a sword.
|
||||||
*
|
*
|
||||||
|
@ -16,6 +16,7 @@ import com.gmail.nossr50.runnables.skills.AwardCombatXpTask;
|
|||||||
import com.gmail.nossr50.skills.acrobatics.AcrobaticsManager;
|
import com.gmail.nossr50.skills.acrobatics.AcrobaticsManager;
|
||||||
import com.gmail.nossr50.skills.archery.ArcheryManager;
|
import com.gmail.nossr50.skills.archery.ArcheryManager;
|
||||||
import com.gmail.nossr50.skills.axes.AxesManager;
|
import com.gmail.nossr50.skills.axes.AxesManager;
|
||||||
|
import com.gmail.nossr50.skills.crossbows.CrossbowManager;
|
||||||
import com.gmail.nossr50.skills.swords.SwordsManager;
|
import com.gmail.nossr50.skills.swords.SwordsManager;
|
||||||
import com.gmail.nossr50.skills.taming.TamingManager;
|
import com.gmail.nossr50.skills.taming.TamingManager;
|
||||||
import com.gmail.nossr50.skills.tridents.TridentManager;
|
import com.gmail.nossr50.skills.tridents.TridentManager;
|
||||||
@ -308,13 +309,49 @@ public final class CombatUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
double distanceMultiplier = archeryManager.distanceXpBonusMultiplier(target, arrow);
|
double distanceMultiplier = archeryManager.distanceXpBonusMultiplier(target, arrow);
|
||||||
double forceMultiplier = 1.0; //Hacky Fix - some plugins spawn arrows and assign them to players after the ProjectileLaunchEvent fires
|
// double forceMultiplier = 1.0; //Hacky Fix - some plugins spawn arrows and assign them to players after the ProjectileLaunchEvent fires
|
||||||
|
|
||||||
if(arrow.hasMetadata(mcMMO.bowForceKey))
|
// if(arrow.hasMetadata(mcMMO.bowForceKey))
|
||||||
forceMultiplier = arrow.getMetadata(mcMMO.bowForceKey).get(0).asDouble();
|
// forceMultiplier = arrow.getMetadata(mcMMO.bowForceKey).get(0).asDouble();
|
||||||
|
|
||||||
applyScaledModifiers(initialDamage, finalDamage, event);
|
applyScaledModifiers(initialDamage, finalDamage, event);
|
||||||
processCombatXP(mcMMOPlayer, target, PrimarySkillType.ARCHERY, forceMultiplier * distanceMultiplier);
|
processCombatXP(mcMMOPlayer, target, PrimarySkillType.ARCHERY, distanceMultiplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void processCrossbowCombat(LivingEntity target, Player player, EntityDamageByEntityEvent event, Projectile arrow) {
|
||||||
|
double initialDamage = event.getDamage();
|
||||||
|
|
||||||
|
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
|
||||||
|
|
||||||
|
//Make sure the profiles been loaded
|
||||||
|
if(mcMMOPlayer == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CrossbowManager crossbowManager = mcMMOPlayer.getCrossbowManager();
|
||||||
|
|
||||||
|
double finalDamage = event.getDamage();
|
||||||
|
|
||||||
|
if (target instanceof Player && PrimarySkillType.UNARMED.getPVPEnabled()) {
|
||||||
|
UnarmedManager unarmedManager = UserManager.getPlayer((Player) target).getUnarmedManager();
|
||||||
|
|
||||||
|
if (unarmedManager.canDeflect()) {
|
||||||
|
event.setCancelled(unarmedManager.deflectCheck());
|
||||||
|
|
||||||
|
if (event.isCancelled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(canUseLimitBreak(player, target, SubSkillType.CROSSBOWS_CROSSBOWS_LIMIT_BREAK))
|
||||||
|
{
|
||||||
|
finalDamage+=getLimitBreakDamage(player, target, SubSkillType.CROSSBOWS_CROSSBOWS_LIMIT_BREAK);
|
||||||
|
}
|
||||||
|
|
||||||
|
double distanceMultiplier = crossbowManager.distanceXpBonusMultiplier(target, arrow);
|
||||||
|
applyScaledModifiers(initialDamage, finalDamage, event);
|
||||||
|
processCombatXP(mcMMOPlayer, target, PrimarySkillType.CROSSBOWS, distanceMultiplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -433,17 +470,31 @@ public final class CombatUtils {
|
|||||||
}
|
}
|
||||||
else if (entityType == EntityType.ARROW || entityType == EntityType.SPECTRAL_ARROW) {
|
else if (entityType == EntityType.ARROW || entityType == EntityType.SPECTRAL_ARROW) {
|
||||||
Projectile arrow = (Projectile) painSource;
|
Projectile arrow = (Projectile) painSource;
|
||||||
ProjectileSource projectileSource = arrow.getShooter();
|
ProjectileSource projectileShooter = arrow.getShooter();
|
||||||
|
|
||||||
//Determine if the arrow belongs to a bow or xbow
|
//Determine if the arrow belongs to a bow or xbow
|
||||||
|
|
||||||
|
|
||||||
if (projectileSource instanceof Player && PrimarySkillType.ARCHERY.shouldProcess(target)) {
|
if (projectileShooter instanceof Player) {
|
||||||
Player player = (Player) projectileSource;
|
Player player = (Player) projectileShooter;
|
||||||
|
|
||||||
|
//Has metadata
|
||||||
|
if(arrow.getMetadata(mcMMO.PROJECTILE_ORIGIN_METAKEY).size() > 0) {
|
||||||
|
if(isProjectileFromBow(arrow)) {
|
||||||
|
if(PrimarySkillType.ARCHERY.shouldProcess(target)) {
|
||||||
if (!Misc.isNPCEntityExcludingVillagers(player) && PrimarySkillType.ARCHERY.getPermissions(player)) {
|
if (!Misc.isNPCEntityExcludingVillagers(player) && PrimarySkillType.ARCHERY.getPermissions(player)) {
|
||||||
processArcheryCombat(target, player, event, arrow);
|
processArcheryCombat(target, player, event, arrow);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
} else if(isProjectileFromCrossbow(arrow)) {
|
||||||
|
if(PrimarySkillType.CROSSBOWS.shouldProcess(target)) {
|
||||||
|
if (!Misc.isNPCEntityExcludingVillagers(player) && PrimarySkillType.CROSSBOWS.getPermissions(player)) {
|
||||||
|
processCrossbowCombat(target, player, event, arrow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (target.getType() != EntityType.CREEPER && !Misc.isNPCEntityExcludingVillagers(player) && PrimarySkillType.TAMING.getPermissions(player)) {
|
if (target.getType() != EntityType.CREEPER && !Misc.isNPCEntityExcludingVillagers(player) && PrimarySkillType.TAMING.getPermissions(player)) {
|
||||||
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
|
McMMOPlayer mcMMOPlayer = UserManager.getPlayer(player);
|
||||||
@ -454,6 +505,14 @@ public final class CombatUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isProjectileFromCrossbow(Projectile arrow) {
|
||||||
|
return arrow.getMetadata(mcMMO.PROJECTILE_ORIGIN_METAKEY).get(0).asInt() == 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isProjectileFromBow(Projectile arrow) {
|
||||||
|
return arrow.getMetadata(mcMMO.PROJECTILE_ORIGIN_METAKEY).get(0).asInt() == 1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This cleans up names from displaying in chat as hearts
|
* This cleans up names from displaying in chat as hearts
|
||||||
* @param entity target entity
|
* @param entity target entity
|
||||||
|
Loading…
Reference in New Issue
Block a user