瀏覽代碼

Archery events & bugfixes

- Added custom events for Skill Shot and Daze.
- Archery metadata is now stored directly as a location, rather than a
string.
- Fixed bug where arrows weren't properly tracked.
- Use HashMap instead of ArrayList for entity tracking.
GJ 11 年之前
父節點
當前提交
965035fa72

+ 1 - 0
Changelog.txt

@@ -51,6 +51,7 @@ Version 1.4.07
  + Added new /mccooldowns command to show all ability cooldowns
  + Commands may now both print text and display a scoreboard
  + Killing a custom entity will automatically add it to the custom entity config file with default values.
+ = Fixed bug where arrow retrieval was not properly detecting entities that already existed in the tracker
  = Fixed bug which allowed players to bypass fishing's exploit prevention
  = Fixed bug where FakeEntityDamageByEntityEvent wasn't being fired
  = Fixed bug with "Skull Splitter" not finding the locale string

+ 33 - 0
src/main/java/com/gmail/nossr50/events/skills/McMMOPlayerCombatEvent.java

@@ -0,0 +1,33 @@
+package com.gmail.nossr50.events.skills;
+
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.Player;
+
+import com.gmail.nossr50.datatypes.skills.SkillType;
+import com.gmail.nossr50.events.fake.FakeEntityDamageByEntityEvent;
+import com.gmail.nossr50.util.player.UserManager;
+
+public abstract class McMMOPlayerCombatEvent extends FakeEntityDamageByEntityEvent {
+    private Player player;
+    private SkillType skill;
+    private int skillLevel;
+
+    public McMMOPlayerCombatEvent(Player player, Entity damager, Entity damagee, DamageCause cause, double damage, SkillType skill) {
+        super(damager, damagee, cause, damage);
+        this.player = player;
+        this.skill = skill;
+        skillLevel = UserManager.getPlayer(player).getProfile().getSkillLevel(skill);
+    }
+
+    public Player getPlayer() {
+        return player;
+    }
+
+    public SkillType getSkill() {
+        return skill;
+    }
+
+    public int getSkillLevel() {
+        return skillLevel;
+    }
+}

+ 13 - 0
src/main/java/com/gmail/nossr50/events/skills/archery/McMMOPlayerArcheryCombatEvent.java

@@ -0,0 +1,13 @@
+package com.gmail.nossr50.events.skills.archery;
+
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.Player;
+
+import com.gmail.nossr50.datatypes.skills.SkillType;
+import com.gmail.nossr50.events.skills.McMMOPlayerCombatEvent;
+
+public class McMMOPlayerArcheryCombatEvent extends McMMOPlayerCombatEvent {
+    public McMMOPlayerArcheryCombatEvent(Player player, Entity damager, Entity damagee, DamageCause cause, double damage) {
+        super(player, damager, damagee, cause, damage, SkillType.ARCHERY);
+    }
+}

+ 24 - 0
src/main/java/com/gmail/nossr50/events/skills/archery/McMMOPlayerArcheryEvent.java

@@ -0,0 +1,24 @@
+package com.gmail.nossr50.events.skills.archery;
+
+import org.bukkit.entity.Player;
+import org.bukkit.event.Cancellable;
+
+import com.gmail.nossr50.datatypes.skills.SkillType;
+import com.gmail.nossr50.events.skills.McMMOPlayerSkillEvent;
+
+public abstract class McMMOPlayerArcheryEvent extends McMMOPlayerSkillEvent implements Cancellable {
+    private boolean cancelled;
+
+    protected McMMOPlayerArcheryEvent(Player player) {
+        super(player, SkillType.ARCHERY);
+        cancelled = false;
+    }
+
+    public boolean isCancelled() {
+        return cancelled;
+    }
+
+    public void setCancelled(boolean cancelled) {
+        this.cancelled = cancelled;
+    }
+}

+ 12 - 0
src/main/java/com/gmail/nossr50/events/skills/archery/McMMOPlayerDazeEvent.java

@@ -0,0 +1,12 @@
+package com.gmail.nossr50.events.skills.archery;
+
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.Player;
+
+import com.gmail.nossr50.skills.archery.Archery;
+
+public class McMMOPlayerDazeEvent extends McMMOPlayerArcheryCombatEvent {
+    public McMMOPlayerDazeEvent(Player player, Entity damager, Entity damagee) {
+        super(player, damager, damagee, DamageCause.PROJECTILE, Archery.dazeModifier);
+    }
+}

+ 10 - 0
src/main/java/com/gmail/nossr50/events/skills/archery/McMMOPlayerSkillShotEvent.java

@@ -0,0 +1,10 @@
+package com.gmail.nossr50.events.skills.archery;
+
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.Player;
+
+public class McMMOPlayerSkillShotEvent extends McMMOPlayerArcheryCombatEvent {
+    public McMMOPlayerSkillShotEvent(Player player, Entity damager, Entity damagee, double damage) {
+        super(player, damager, damagee, DamageCause.PROJECTILE, damage);
+    }
+}

+ 2 - 2
src/main/java/com/gmail/nossr50/listeners/EntityListener.java

@@ -74,7 +74,7 @@ public class EntityListener implements Listener {
         }
 
         projectile.setMetadata(mcMMO.bowForceKey, new FixedMetadataValue(plugin, Math.min(event.getForce() * AdvancedConfig.getInstance().getForceMultiplier(), 1.0)));
-        projectile.setMetadata(mcMMO.arrowDistanceKey, new FixedMetadataValue(plugin, Archery.locationToString(projectile.getLocation())));
+        projectile.setMetadata(mcMMO.arrowDistanceKey, new FixedMetadataValue(plugin, projectile.getLocation()));
     }
 
     @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
@@ -86,7 +86,7 @@ public class EntityListener implements Listener {
         }
 
         projectile.setMetadata(mcMMO.bowForceKey, new FixedMetadataValue(plugin, 1.0));
-        projectile.setMetadata(mcMMO.arrowDistanceKey, new FixedMetadataValue(plugin, Archery.locationToString(projectile.getLocation())));
+        projectile.setMetadata(mcMMO.arrowDistanceKey, new FixedMetadataValue(plugin, projectile.getLocation()));
     }
 
     /**

+ 19 - 31
src/main/java/com/gmail/nossr50/skills/archery/Archery.java

@@ -1,20 +1,18 @@
 package com.gmail.nossr50.skills.archery;
 
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
 
-import org.bukkit.Location;
 import org.bukkit.Material;
 import org.bukkit.entity.LivingEntity;
 import org.bukkit.inventory.ItemStack;
 
-import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.config.AdvancedConfig;
 import com.gmail.nossr50.util.Misc;
 
 public class Archery {
-    private static List<TrackedEntity> trackedEntities = new ArrayList<TrackedEntity>();
+    private static Map<UUID, TrackedEntity> trackedEntities = new HashMap<UUID, TrackedEntity>();
 
     public static int    retrieveMaxBonusLevel = AdvancedConfig.getInstance().getRetrieveMaxBonusLevel();
     public static double retrieveMaxChance     = AdvancedConfig.getInstance().getRetrieveChanceMax();
@@ -31,11 +29,11 @@ public class Archery {
     public static final double DISTANCE_XP_MULTIPLIER = 0.025;
 
     protected static void incrementTrackerValue(LivingEntity livingEntity) {
-        for (TrackedEntity trackedEntity : trackedEntities) {
-            if (trackedEntity.getLivingEntity().getEntityId() == livingEntity.getEntityId()) {
-                trackedEntity.incrementArrowCount();
-                return;
-            }
+        TrackedEntity trackedEntity = trackedEntities.get(livingEntity.getUniqueId());
+
+        if (trackedEntity != null) {
+            trackedEntity.incrementArrowCount();
+            return;
         }
 
         addToTracker(livingEntity); // If the entity isn't tracked yet
@@ -45,11 +43,11 @@ public class Archery {
         TrackedEntity trackedEntity = new TrackedEntity(livingEntity);
 
         trackedEntity.incrementArrowCount();
-        trackedEntities.add(trackedEntity);
+        trackedEntities.put(livingEntity.getUniqueId(), trackedEntity);
     }
 
-    protected static void removeFromTracker(TrackedEntity trackedEntity) {
-        trackedEntities.remove(trackedEntity);
+    protected static void removeFromTracker(UUID id) {
+        trackedEntities.remove(id);
     }
 
     /**
@@ -58,24 +56,14 @@ public class Archery {
      * @param livingEntity The entity hit by the arrows
      */
     public static void arrowRetrievalCheck(LivingEntity livingEntity) {
-        for (Iterator<TrackedEntity> entityIterator = trackedEntities.iterator(); entityIterator.hasNext();) {
-            TrackedEntity trackedEntity = entityIterator.next();
-
-            if (trackedEntity.getID() == livingEntity.getUniqueId()) {
-                Misc.dropItems(livingEntity.getLocation(), new ItemStack(Material.ARROW), trackedEntity.getArrowCount());
-                entityIterator.remove();
-                return;
-            }
-        }
-    }
+        UUID id = livingEntity.getUniqueId();
+        TrackedEntity trackedEntity = trackedEntities.get(id);
 
-    public static Location stringToLocation(String location) {
-        String[] values = location.split(",");
-
-        return new Location(mcMMO.p.getServer().getWorld(values[0]), Double.parseDouble(values[1]), Double.parseDouble(values[2]), Double.parseDouble(values[3]), Float.parseFloat(values[4]), Float.parseFloat(values[5]));
-    }
+        if (trackedEntity == null) {
+            return;
+        }
 
-    public static String locationToString(Location location) {
-        return location.getWorld().getName() + "," + location.getX() + "," + location.getY() + "," + location.getZ() + "," + location.getYaw() + "," + location.getPitch();
+        Misc.dropItems(livingEntity.getLocation(), new ItemStack(Material.ARROW), trackedEntity.getArrowCount());
+        removeFromTracker(id);
     }
 }

+ 45 - 17
src/main/java/com/gmail/nossr50/skills/archery/ArcheryManager.java

@@ -5,19 +5,19 @@ import org.bukkit.entity.Arrow;
 import org.bukkit.entity.Entity;
 import org.bukkit.entity.LivingEntity;
 import org.bukkit.entity.Player;
-import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
 import org.bukkit.potion.PotionEffect;
 import org.bukkit.potion.PotionEffectType;
 
 import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.datatypes.player.McMMOPlayer;
 import com.gmail.nossr50.datatypes.skills.SkillType;
+import com.gmail.nossr50.events.skills.archery.McMMOPlayerDazeEvent;
+import com.gmail.nossr50.events.skills.archery.McMMOPlayerSkillShotEvent;
 import com.gmail.nossr50.locale.LocaleLoader;
 import com.gmail.nossr50.skills.SkillManager;
 import com.gmail.nossr50.util.Misc;
 import com.gmail.nossr50.util.Permissions;
 import com.gmail.nossr50.util.player.UserManager;
-import com.gmail.nossr50.util.skills.CombatUtils;
 import com.gmail.nossr50.util.skills.SkillUtils;
 
 public class ArcheryManager extends SkillManager {
@@ -26,15 +26,15 @@ public class ArcheryManager extends SkillManager {
     }
 
     public boolean canDaze(LivingEntity target) {
-        return target instanceof Player && Permissions.daze(getPlayer());
+        return target instanceof Player && Permissions.daze(getPlayer()) && SkillUtils.activationSuccessful(getSkillLevel(), getActivationChance(), Archery.dazeMaxBonus, Archery.dazeMaxBonusLevel);
     }
 
-    public boolean canSkillShot() {
+    public boolean canUseSkillShot() {
         return getSkillLevel() >= Archery.skillShotIncreaseLevel && Permissions.bonusDamage(getPlayer(), skill);
     }
 
-    public boolean canTrackArrows() {
-        return Permissions.arrowRetrieval(getPlayer());
+    public boolean canTrack(Arrow arrow) {
+        return Permissions.arrowRetrieval(getPlayer()) && !arrow.hasMetadata(mcMMO.infiniteArrowKey) && SkillUtils.activationSuccessful(getSkillLevel(), getActivationChance(), Archery.retrieveMaxChance, Archery.retrieveMaxBonusLevel);
     }
 
     /**
@@ -44,7 +44,7 @@ public class ArcheryManager extends SkillManager {
      * @param damager The {@link Entity} who shot the arrow
      */
     public void distanceXpBonus(LivingEntity target, Entity damager) {
-        Location firedLocation = Archery.stringToLocation(damager.getMetadata(mcMMO.arrowDistanceKey).get(0).asString());
+        Location firedLocation = (Location) damager.getMetadata(mcMMO.arrowDistanceKey).get(0).value();
         Location targetLocation = target.getLocation();
 
         if (firedLocation.getWorld() != targetLocation.getWorld()) {
@@ -58,39 +58,52 @@ public class ArcheryManager extends SkillManager {
      * Track arrows fired for later retrieval.
      *
      * @param target The {@link LivingEntity} damaged by the arrow
+     * @param arrow The {@link Arrow} that damaged the target
      */
-    public void trackArrows(LivingEntity target) {
-        if (SkillUtils.activationSuccessful(getSkillLevel(), getActivationChance(), Archery.retrieveMaxChance, Archery.retrieveMaxBonusLevel)) {
-            Archery.incrementTrackerValue(target);
+    public void trackArrow(LivingEntity target, Arrow arrow) {
+        if (!canTrack(arrow)) {
+            return;
         }
+
+        Archery.incrementTrackerValue(target);
     }
 
     /**
      * Handle the effects of the Daze ability
      *
-     * @param defender The {@link Player} being affected by the ability
+     * @param target The {@link LivingEntity} being affected by the ability
      * @param arrow The {@link Arrow} that was fired
      */
-    public double daze(Player defender, Arrow arrow) {
-        if (!SkillUtils.activationSuccessful(getSkillLevel(), getActivationChance(), Archery.dazeMaxBonus, Archery.dazeMaxBonusLevel)) {
+    public double daze(LivingEntity target, Arrow arrow) {
+        if (!canDaze(target)) {
             return 0;
         }
 
+        Player attacker = getPlayer();
+
+        McMMOPlayerDazeEvent event = new McMMOPlayerDazeEvent(attacker, arrow, target);
+        mcMMO.p.getServer().getPluginManager().callEvent(event);
+
+        if (event.isCancelled()) {
+            return 0;
+        }
+
+        Player defender = (Player) target;
         Location dazedLocation = defender.getLocation();
         dazedLocation.setPitch(90 - Misc.getRandom().nextInt(181));
 
         defender.teleport(dazedLocation);
-        defender.addPotionEffect(new PotionEffect(PotionEffectType.CONFUSION, 20 * 10, 10));
+        defender.addPotionEffect(new PotionEffect(PotionEffectType.CONFUSION, Misc.TICK_CONVERSION_FACTOR * 10, 10));
 
         if (UserManager.getPlayer(defender).useChatNotifications()) {
             defender.sendMessage(LocaleLoader.getString("Combat.TouchedFuzzy"));
         }
 
         if (mcMMOPlayer.useChatNotifications()) {
-            getPlayer().sendMessage(LocaleLoader.getString("Combat.TargetDazed"));
+            attacker.sendMessage(LocaleLoader.getString("Combat.TargetDazed"));
         }
 
-        return CombatUtils.callFakeDamageEvent(arrow, defender, DamageCause.PROJECTILE, Archery.dazeModifier);
+        return event.getDamage();
     }
 
     /**
@@ -101,9 +114,24 @@ public class ArcheryManager extends SkillManager {
      * @param arrow The {@link Arrow} that was fired
      */
     public double skillShot(LivingEntity target, double damage, Arrow arrow) {
+        if (!canUseSkillShot()) {
+            return 0;
+        }
+
+        McMMOPlayerSkillShotEvent event = new McMMOPlayerSkillShotEvent(getPlayer(), arrow, target, calculateSkillShotBonus(damage));
+        mcMMO.p.getServer().getPluginManager().callEvent(event);
+
+        if (event.isCancelled()) {
+            return 0;
+        }
+
+        return event.getDamage();
+    }
+
+    private double calculateSkillShotBonus(double damage) {
         double damageBonusPercent = Math.min(((getSkillLevel() / Archery.skillShotIncreaseLevel) * Archery.skillShotIncreasePercentage), Archery.skillShotMaxBonusPercentage);
         double archeryBonus = Math.min(damage * damageBonusPercent, Archery.skillShotMaxBonusDamage);
 
-        return CombatUtils.callFakeDamageEvent(arrow, target, DamageCause.PROJECTILE, archeryBonus);
+        return archeryBonus;
     }
 }

+ 1 - 5
src/main/java/com/gmail/nossr50/skills/archery/TrackedEntity.java

@@ -22,15 +22,11 @@ public class TrackedEntity extends BukkitRunnable {
     @Override
     public void run() {
         if (!livingEntity.isValid()) {
-            Archery.removeFromTracker(this);
+            Archery.removeFromTracker(id);
             this.cancel();
         }
     }
 
-    protected LivingEntity getLivingEntity() {
-        return livingEntity;
-    }
-
     protected UUID getID() {
         return id;
     }

+ 3 - 12
src/main/java/com/gmail/nossr50/util/skills/CombatUtils.java

@@ -18,7 +18,6 @@ import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
 import org.bukkit.inventory.ItemStack;
 
 import com.gmail.nossr50.mcMMO;
-import com.gmail.nossr50.config.Config;
 import com.gmail.nossr50.config.experience.ExperienceConfig;
 import com.gmail.nossr50.datatypes.player.McMMOPlayer;
 import com.gmail.nossr50.datatypes.skills.SkillType;
@@ -167,18 +166,10 @@ public final class CombatUtils {
             }
         }
 
-        if (archeryManager.canSkillShot()) {
-            finalDamage += archeryManager.skillShot(target, initialDamage, arrow);
-        }
-
-        if (archeryManager.canDaze(target)) {
-            finalDamage += archeryManager.daze((Player) target, arrow);
-        }
-
-        if (!arrow.hasMetadata(mcMMO.infiniteArrowKey) && archeryManager.canTrackArrows()) {
-            archeryManager.trackArrows(target);
-        }
+        finalDamage += archeryManager.skillShot(target, initialDamage, arrow);
+        finalDamage += archeryManager.daze(target, arrow);
 
+        archeryManager.trackArrow(target, arrow);
         archeryManager.distanceXpBonus(target, arrow);
 
         event.setDamage(finalDamage);