mirror of
				https://github.com/mcMMO-Dev/mcMMO.git
				synced 2025-11-04 02:53:43 +01:00 
			
		
		
		
	Crossbow multi-shot arrows that bounce are no longer pickup-able
This commit is contained in:
		
							
								
								
									
										2
									
								
								pom.xml
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								pom.xml
									
									
									
									
									
								
							@@ -2,7 +2,7 @@
 | 
			
		||||
    <modelVersion>4.0.0</modelVersion>
 | 
			
		||||
    <groupId>com.gmail.nossr50.mcMMO</groupId>
 | 
			
		||||
    <artifactId>mcMMO</artifactId>
 | 
			
		||||
    <version>2.2.000-BETA-07-SNAPSHOT</version>
 | 
			
		||||
    <version>2.2.000-BETA-08-SNAPSHOT</version>
 | 
			
		||||
    <name>mcMMO</name>
 | 
			
		||||
    <url>https://github.com/mcMMO-Dev/mcMMO</url>
 | 
			
		||||
    <scm>
 | 
			
		||||
 
 | 
			
		||||
@@ -152,17 +152,20 @@ public class EntityListener implements Listener {
 | 
			
		||||
                    return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Projectile projectile = event.getEntity();
 | 
			
		||||
            EntityType entityType = projectile.getType();
 | 
			
		||||
            if(event.getEntity() instanceof Arrow arrow) {
 | 
			
		||||
                // Delayed metadata cleanup in case other cleanup hooks fail
 | 
			
		||||
                CombatUtils.delayArrowMetaCleanup(arrow);
 | 
			
		||||
 | 
			
		||||
            if(projectile instanceof Arrow arrow) {
 | 
			
		||||
                CombatUtils.delayArrowMetaCleanup(arrow); //Cleans up metadata 1 minute from now in case other collection methods fall through
 | 
			
		||||
                // If fired from an item with multi-shot, we need to track
 | 
			
		||||
                if(ItemUtils.doesPlayerHaveEnchantmentInHands(player, "multishot")) {
 | 
			
		||||
                    arrow.setMetadata(MetadataConstants.METADATA_KEY_MULTI_SHOT_ARROW, MetadataConstants.MCMMO_METADATA_VALUE);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if(!projectile.hasMetadata(MetadataConstants.METADATA_KEY_BOW_FORCE))
 | 
			
		||||
                    projectile.setMetadata(MetadataConstants.METADATA_KEY_BOW_FORCE, new FixedMetadataValue(pluginRef, 1.0));
 | 
			
		||||
                if(!arrow.hasMetadata(MetadataConstants.METADATA_KEY_BOW_FORCE))
 | 
			
		||||
                    arrow.setMetadata(MetadataConstants.METADATA_KEY_BOW_FORCE, new FixedMetadataValue(pluginRef, 1.0));
 | 
			
		||||
 | 
			
		||||
                if(!projectile.hasMetadata(MetadataConstants.METADATA_KEY_ARROW_DISTANCE))
 | 
			
		||||
                    projectile.setMetadata(MetadataConstants.METADATA_KEY_ARROW_DISTANCE, new FixedMetadataValue(pluginRef, arrow.getLocation()));
 | 
			
		||||
                if(!arrow.hasMetadata(MetadataConstants.METADATA_KEY_ARROW_DISTANCE))
 | 
			
		||||
                    arrow.setMetadata(MetadataConstants.METADATA_KEY_ARROW_DISTANCE, new FixedMetadataValue(pluginRef, arrow.getLocation()));
 | 
			
		||||
 | 
			
		||||
                //Check both hands
 | 
			
		||||
                if(ItemUtils.doesPlayerHaveEnchantmentInHands(player, "piercing")) {
 | 
			
		||||
@@ -170,7 +173,7 @@ public class EntityListener implements Listener {
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (ProbabilityUtil.isSkillRNGSuccessful(SubSkillType.ARCHERY_ARROW_RETRIEVAL, player)) {
 | 
			
		||||
                    projectile.setMetadata(MetadataConstants.METADATA_KEY_TRACKED_ARROW, MetadataConstants.MCMMO_METADATA_VALUE);
 | 
			
		||||
                    arrow.setMetadata(MetadataConstants.METADATA_KEY_TRACKED_ARROW, MetadataConstants.MCMMO_METADATA_VALUE);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
package com.gmail.nossr50.skills.crossbows;
 | 
			
		||||
 | 
			
		||||
import com.gmail.nossr50.datatypes.player.McMMOPlayer;
 | 
			
		||||
import com.gmail.nossr50.util.MetadataConstants;
 | 
			
		||||
import com.gmail.nossr50.util.player.UserManager;
 | 
			
		||||
import org.bukkit.entity.Arrow;
 | 
			
		||||
import org.bukkit.entity.Player;
 | 
			
		||||
@@ -13,17 +14,29 @@ import static com.gmail.nossr50.util.skills.ProjectileUtils.getNormal;
 | 
			
		||||
 * Util class for crossbows.
 | 
			
		||||
 */
 | 
			
		||||
public class Crossbows {
 | 
			
		||||
    /**
 | 
			
		||||
     * Process events that may happen from a crossbow hitting an entity.
 | 
			
		||||
     *
 | 
			
		||||
     * @param event      the projectile hit event
 | 
			
		||||
     * @param pluginRef  the plugin ref
 | 
			
		||||
     * @param arrow      the arrow
 | 
			
		||||
     */
 | 
			
		||||
    public static void processCrossbows(ProjectileHitEvent event, Plugin pluginRef, Arrow arrow) {
 | 
			
		||||
        if (arrow.getShooter() instanceof Player) {
 | 
			
		||||
            McMMOPlayer mmoPlayer = UserManager.getPlayer((Player) arrow.getShooter());
 | 
			
		||||
            if (mmoPlayer == null)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            processTrickShot(event, pluginRef, arrow, mmoPlayer);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static void processTrickShot(ProjectileHitEvent event, Plugin pluginRef, Arrow arrow, McMMOPlayer mmoPlayer) {
 | 
			
		||||
        if(event.getHitBlock() != null && event.getHitBlockFace() != null) {
 | 
			
		||||
            if (arrow.getShooter() instanceof Player) {
 | 
			
		||||
                McMMOPlayer mmoPlayer = UserManager.getPlayer((Player) arrow.getShooter());
 | 
			
		||||
                if (mmoPlayer != null) {
 | 
			
		||||
                    mmoPlayer.getCrossbowsManager().handleRicochet(
 | 
			
		||||
                            pluginRef,
 | 
			
		||||
                            arrow,
 | 
			
		||||
                            getNormal(event.getHitBlockFace()));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            mmoPlayer.getCrossbowsManager().handleRicochet(
 | 
			
		||||
                    pluginRef,
 | 
			
		||||
                    arrow,
 | 
			
		||||
                    getNormal(event.getHitBlockFace()));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -8,8 +8,10 @@ import com.gmail.nossr50.skills.SkillManager;
 | 
			
		||||
import com.gmail.nossr50.util.MetadataConstants;
 | 
			
		||||
import com.gmail.nossr50.util.Permissions;
 | 
			
		||||
import com.gmail.nossr50.util.random.ProbabilityUtil;
 | 
			
		||||
import com.gmail.nossr50.util.skills.ProjectileUtils;
 | 
			
		||||
import com.gmail.nossr50.util.skills.RankUtils;
 | 
			
		||||
import org.bukkit.Location;
 | 
			
		||||
import org.bukkit.entity.AbstractArrow;
 | 
			
		||||
import org.bukkit.entity.Arrow;
 | 
			
		||||
import org.bukkit.entity.Player;
 | 
			
		||||
import org.bukkit.metadata.FixedMetadataValue;
 | 
			
		||||
@@ -18,6 +20,8 @@ import org.bukkit.projectiles.ProjectileSource;
 | 
			
		||||
import org.bukkit.util.Vector;
 | 
			
		||||
import org.jetbrains.annotations.NotNull;
 | 
			
		||||
 | 
			
		||||
import static com.gmail.nossr50.util.skills.CombatUtils.delayArrowMetaCleanup;
 | 
			
		||||
 | 
			
		||||
public class CrossbowsManager extends SkillManager {
 | 
			
		||||
    public CrossbowsManager(McMMOPlayer mmoPlayer) {
 | 
			
		||||
        super(mmoPlayer, PrimarySkillType.CROSSBOWS);
 | 
			
		||||
@@ -52,7 +56,6 @@ public class CrossbowsManager extends SkillManager {
 | 
			
		||||
        final Vector reflectedDirection = arrowInBlockVector.subtract(normal.multiply(2 * arrowInBlockVector.dot(normal)));
 | 
			
		||||
        final Vector inverseNormal = normal.multiply(-1);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        // check the angle of the arrow against the inverse normal to see if the angle was too shallow
 | 
			
		||||
        // only checks angle on the first bounce
 | 
			
		||||
        if (bounceCount == 0 && arrowInBlockVector.angle(inverseNormal) < Math.PI / 4) {
 | 
			
		||||
@@ -60,15 +63,24 @@ public class CrossbowsManager extends SkillManager {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Spawn new arrow with the reflected direction
 | 
			
		||||
        Arrow arrow = originalArrow.getWorld().spawnArrow(origin,
 | 
			
		||||
                reflectedDirection, 1, 1);
 | 
			
		||||
        arrow.setShooter(originalArrowShooter);
 | 
			
		||||
        arrow.setMetadata(MetadataConstants.METADATA_KEY_BOUNCE_COUNT,
 | 
			
		||||
        Arrow spawnedArrow = originalArrow.getWorld().spawnArrow(origin, reflectedDirection, 1, 1);
 | 
			
		||||
        ProjectileUtils.copyArrowMetadata(pluginRef, originalArrow, spawnedArrow);
 | 
			
		||||
        originalArrow.remove();
 | 
			
		||||
        // copy metadata from old arrow
 | 
			
		||||
        spawnedArrow.setShooter(originalArrowShooter);
 | 
			
		||||
        spawnedArrow.setMetadata(MetadataConstants.METADATA_KEY_BOUNCE_COUNT,
 | 
			
		||||
                new FixedMetadataValue(pluginRef, bounceCount + 1));
 | 
			
		||||
        arrow.setMetadata(MetadataConstants.METADATA_KEY_SPAWNED_ARROW,
 | 
			
		||||
        spawnedArrow.setMetadata(MetadataConstants.METADATA_KEY_SPAWNED_ARROW,
 | 
			
		||||
                new FixedMetadataValue(pluginRef, originalArrowShooter));
 | 
			
		||||
 | 
			
		||||
        originalArrow.remove();
 | 
			
		||||
        // Don't allow multi-shot or infinite arrows to be picked up
 | 
			
		||||
        if (spawnedArrow.hasMetadata(MetadataConstants.METADATA_KEY_MULTI_SHOT_ARROW)
 | 
			
		||||
                || spawnedArrow.hasMetadata(MetadataConstants.METADATA_KEY_INF_ARROW)) {
 | 
			
		||||
            spawnedArrow.setPickupStatus(AbstractArrow.PickupStatus.DISALLOWED);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Schedule cleanup of metadata in case metadata cleanup fails
 | 
			
		||||
        delayArrowMetaCleanup(spawnedArrow);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public int getTrickShotMaxBounceCount() {
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,7 @@ public class MetadataConstants {
 | 
			
		||||
     */
 | 
			
		||||
    public static final @NotNull String METADATA_KEY_REPLANT = "mcMMO: Recently Replanted";
 | 
			
		||||
    public static final @NotNull String METADATA_KEY_SPAWNED_ARROW = "mcMMO: Spawned Arrow";
 | 
			
		||||
    public static final @NotNull String METADATA_KEY_MULTI_SHOT_ARROW = "mcMMO: Multi-shot Arrow";
 | 
			
		||||
    public static final @NotNull String METADATA_KEY_BOUNCE_COUNT = "mcMMO: Arrow Bounce Count";
 | 
			
		||||
    public static final @NotNull String METADATA_KEY_EXPLOSION_FROM_RUPTURE = "mcMMO: Rupture Explosion";
 | 
			
		||||
    public static final @NotNull String METADATA_KEY_FISH_HOOK_REF = "mcMMO: Fish Hook Tracker";
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,8 @@ import com.gmail.nossr50.mcMMO;
 | 
			
		||||
import com.gmail.nossr50.util.MetadataConstants;
 | 
			
		||||
import org.bukkit.block.BlockFace;
 | 
			
		||||
import org.bukkit.entity.Arrow;
 | 
			
		||||
import org.bukkit.metadata.FixedMetadataValue;
 | 
			
		||||
import org.bukkit.plugin.Plugin;
 | 
			
		||||
import org.bukkit.util.Vector;
 | 
			
		||||
import org.jetbrains.annotations.NotNull;
 | 
			
		||||
 | 
			
		||||
@@ -42,5 +44,37 @@ public class ProjectileUtils {
 | 
			
		||||
        if(arrow.hasMetadata(MetadataConstants.METADATA_KEY_SPAWNED_ARROW)) {
 | 
			
		||||
            arrow.removeMetadata(MetadataConstants.METADATA_KEY_SPAWNED_ARROW, mcMMO.p);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(arrow.hasMetadata(MetadataConstants.METADATA_KEY_MULTI_SHOT_ARROW)) {
 | 
			
		||||
            arrow.removeMetadata(MetadataConstants.METADATA_KEY_MULTI_SHOT_ARROW, mcMMO.p);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static void copyArrowMetadata(@NotNull Plugin pluginRef, @NotNull Arrow arrowToCopy, @NotNull Arrow newArrow) {
 | 
			
		||||
        if(arrowToCopy.hasMetadata(MetadataConstants.METADATA_KEY_INF_ARROW)) {
 | 
			
		||||
            newArrow.setMetadata(MetadataConstants.METADATA_KEY_INF_ARROW,
 | 
			
		||||
                    arrowToCopy.getMetadata(MetadataConstants.METADATA_KEY_INF_ARROW).get(0));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(arrowToCopy.hasMetadata(MetadataConstants.METADATA_KEY_BOW_FORCE)) {
 | 
			
		||||
            newArrow.setMetadata(MetadataConstants.METADATA_KEY_BOW_FORCE,
 | 
			
		||||
                    new FixedMetadataValue(pluginRef,
 | 
			
		||||
                            arrowToCopy.getMetadata(MetadataConstants.METADATA_KEY_BOW_FORCE).get(0).asDouble()));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(arrowToCopy.hasMetadata(MetadataConstants.METADATA_KEY_ARROW_DISTANCE)) {
 | 
			
		||||
            newArrow.setMetadata(MetadataConstants.METADATA_KEY_ARROW_DISTANCE,
 | 
			
		||||
                    arrowToCopy.getMetadata(MetadataConstants.METADATA_KEY_ARROW_DISTANCE).get(0));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(arrowToCopy.hasMetadata(MetadataConstants.METADATA_KEY_SPAWNED_ARROW)) {
 | 
			
		||||
            newArrow.setMetadata(MetadataConstants.METADATA_KEY_SPAWNED_ARROW,
 | 
			
		||||
                    arrowToCopy.getMetadata(MetadataConstants.METADATA_KEY_SPAWNED_ARROW).get(0));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if(arrowToCopy.hasMetadata(MetadataConstants.METADATA_KEY_MULTI_SHOT_ARROW)) {
 | 
			
		||||
            newArrow.setMetadata(MetadataConstants.METADATA_KEY_MULTI_SHOT_ARROW,
 | 
			
		||||
                    arrowToCopy.getMetadata(MetadataConstants.METADATA_KEY_MULTI_SHOT_ARROW).get(0));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user