mirror of
https://github.com/mcMMO-Dev/mcMMO.git
synced 2024-11-24 06:06:45 +01:00
Crossbow multi-shot arrows that bounce are no longer pickup-able
This commit is contained in:
parent
b3b8a12b6d
commit
66a4886ee4
2
pom.xml
2
pom.xml
@ -2,7 +2,7 @@
|
|||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>com.gmail.nossr50.mcMMO</groupId>
|
<groupId>com.gmail.nossr50.mcMMO</groupId>
|
||||||
<artifactId>mcMMO</artifactId>
|
<artifactId>mcMMO</artifactId>
|
||||||
<version>2.2.000-BETA-07-SNAPSHOT</version>
|
<version>2.2.000-BETA-08-SNAPSHOT</version>
|
||||||
<name>mcMMO</name>
|
<name>mcMMO</name>
|
||||||
<url>https://github.com/mcMMO-Dev/mcMMO</url>
|
<url>https://github.com/mcMMO-Dev/mcMMO</url>
|
||||||
<scm>
|
<scm>
|
||||||
|
@ -152,17 +152,20 @@ public class EntityListener implements Listener {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Projectile projectile = event.getEntity();
|
if(event.getEntity() instanceof Arrow arrow) {
|
||||||
EntityType entityType = projectile.getType();
|
// Delayed metadata cleanup in case other cleanup hooks fail
|
||||||
|
CombatUtils.delayArrowMetaCleanup(arrow);
|
||||||
|
|
||||||
if(projectile instanceof Arrow arrow) {
|
// If fired from an item with multi-shot, we need to track
|
||||||
CombatUtils.delayArrowMetaCleanup(arrow); //Cleans up metadata 1 minute from now in case other collection methods fall through
|
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))
|
if(!arrow.hasMetadata(MetadataConstants.METADATA_KEY_BOW_FORCE))
|
||||||
projectile.setMetadata(MetadataConstants.METADATA_KEY_BOW_FORCE, new FixedMetadataValue(pluginRef, 1.0));
|
arrow.setMetadata(MetadataConstants.METADATA_KEY_BOW_FORCE, new FixedMetadataValue(pluginRef, 1.0));
|
||||||
|
|
||||||
if(!projectile.hasMetadata(MetadataConstants.METADATA_KEY_ARROW_DISTANCE))
|
if(!arrow.hasMetadata(MetadataConstants.METADATA_KEY_ARROW_DISTANCE))
|
||||||
projectile.setMetadata(MetadataConstants.METADATA_KEY_ARROW_DISTANCE, new FixedMetadataValue(pluginRef, arrow.getLocation()));
|
arrow.setMetadata(MetadataConstants.METADATA_KEY_ARROW_DISTANCE, new FixedMetadataValue(pluginRef, arrow.getLocation()));
|
||||||
|
|
||||||
//Check both hands
|
//Check both hands
|
||||||
if(ItemUtils.doesPlayerHaveEnchantmentInHands(player, "piercing")) {
|
if(ItemUtils.doesPlayerHaveEnchantmentInHands(player, "piercing")) {
|
||||||
@ -170,7 +173,7 @@ public class EntityListener implements Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ProbabilityUtil.isSkillRNGSuccessful(SubSkillType.ARCHERY_ARROW_RETRIEVAL, player)) {
|
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;
|
package com.gmail.nossr50.skills.crossbows;
|
||||||
|
|
||||||
import com.gmail.nossr50.datatypes.player.McMMOPlayer;
|
import com.gmail.nossr50.datatypes.player.McMMOPlayer;
|
||||||
|
import com.gmail.nossr50.util.MetadataConstants;
|
||||||
import com.gmail.nossr50.util.player.UserManager;
|
import com.gmail.nossr50.util.player.UserManager;
|
||||||
import org.bukkit.entity.Arrow;
|
import org.bukkit.entity.Arrow;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
@ -13,17 +14,29 @@ import static com.gmail.nossr50.util.skills.ProjectileUtils.getNormal;
|
|||||||
* Util class for crossbows.
|
* Util class for crossbows.
|
||||||
*/
|
*/
|
||||||
public class 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) {
|
public static void processCrossbows(ProjectileHitEvent event, Plugin pluginRef, Arrow arrow) {
|
||||||
if(event.getHitBlock() != null && event.getHitBlockFace() != null) {
|
|
||||||
if (arrow.getShooter() instanceof Player) {
|
if (arrow.getShooter() instanceof Player) {
|
||||||
McMMOPlayer mmoPlayer = UserManager.getPlayer((Player) arrow.getShooter());
|
McMMOPlayer mmoPlayer = UserManager.getPlayer((Player) arrow.getShooter());
|
||||||
if (mmoPlayer != null) {
|
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) {
|
||||||
mmoPlayer.getCrossbowsManager().handleRicochet(
|
mmoPlayer.getCrossbowsManager().handleRicochet(
|
||||||
pluginRef,
|
pluginRef,
|
||||||
arrow,
|
arrow,
|
||||||
getNormal(event.getHitBlockFace()));
|
getNormal(event.getHitBlockFace()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,10 @@ import com.gmail.nossr50.skills.SkillManager;
|
|||||||
import com.gmail.nossr50.util.MetadataConstants;
|
import com.gmail.nossr50.util.MetadataConstants;
|
||||||
import com.gmail.nossr50.util.Permissions;
|
import com.gmail.nossr50.util.Permissions;
|
||||||
import com.gmail.nossr50.util.random.ProbabilityUtil;
|
import com.gmail.nossr50.util.random.ProbabilityUtil;
|
||||||
|
import com.gmail.nossr50.util.skills.ProjectileUtils;
|
||||||
import com.gmail.nossr50.util.skills.RankUtils;
|
import com.gmail.nossr50.util.skills.RankUtils;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.entity.AbstractArrow;
|
||||||
import org.bukkit.entity.Arrow;
|
import org.bukkit.entity.Arrow;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.metadata.FixedMetadataValue;
|
import org.bukkit.metadata.FixedMetadataValue;
|
||||||
@ -18,6 +20,8 @@ import org.bukkit.projectiles.ProjectileSource;
|
|||||||
import org.bukkit.util.Vector;
|
import org.bukkit.util.Vector;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import static com.gmail.nossr50.util.skills.CombatUtils.delayArrowMetaCleanup;
|
||||||
|
|
||||||
public class CrossbowsManager extends SkillManager {
|
public class CrossbowsManager extends SkillManager {
|
||||||
public CrossbowsManager(McMMOPlayer mmoPlayer) {
|
public CrossbowsManager(McMMOPlayer mmoPlayer) {
|
||||||
super(mmoPlayer, PrimarySkillType.CROSSBOWS);
|
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 reflectedDirection = arrowInBlockVector.subtract(normal.multiply(2 * arrowInBlockVector.dot(normal)));
|
||||||
final Vector inverseNormal = normal.multiply(-1);
|
final Vector inverseNormal = normal.multiply(-1);
|
||||||
|
|
||||||
|
|
||||||
// check the angle of the arrow against the inverse normal to see if the angle was too shallow
|
// 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
|
// only checks angle on the first bounce
|
||||||
if (bounceCount == 0 && arrowInBlockVector.angle(inverseNormal) < Math.PI / 4) {
|
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
|
// Spawn new arrow with the reflected direction
|
||||||
Arrow arrow = originalArrow.getWorld().spawnArrow(origin,
|
Arrow spawnedArrow = originalArrow.getWorld().spawnArrow(origin, reflectedDirection, 1, 1);
|
||||||
reflectedDirection, 1, 1);
|
ProjectileUtils.copyArrowMetadata(pluginRef, originalArrow, spawnedArrow);
|
||||||
arrow.setShooter(originalArrowShooter);
|
originalArrow.remove();
|
||||||
arrow.setMetadata(MetadataConstants.METADATA_KEY_BOUNCE_COUNT,
|
// copy metadata from old arrow
|
||||||
|
spawnedArrow.setShooter(originalArrowShooter);
|
||||||
|
spawnedArrow.setMetadata(MetadataConstants.METADATA_KEY_BOUNCE_COUNT,
|
||||||
new FixedMetadataValue(pluginRef, bounceCount + 1));
|
new FixedMetadataValue(pluginRef, bounceCount + 1));
|
||||||
arrow.setMetadata(MetadataConstants.METADATA_KEY_SPAWNED_ARROW,
|
spawnedArrow.setMetadata(MetadataConstants.METADATA_KEY_SPAWNED_ARROW,
|
||||||
new FixedMetadataValue(pluginRef, originalArrowShooter));
|
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() {
|
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_REPLANT = "mcMMO: Recently Replanted";
|
||||||
public static final @NotNull String METADATA_KEY_SPAWNED_ARROW = "mcMMO: Spawned Arrow";
|
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_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_EXPLOSION_FROM_RUPTURE = "mcMMO: Rupture Explosion";
|
||||||
public static final @NotNull String METADATA_KEY_FISH_HOOK_REF = "mcMMO: Fish Hook Tracker";
|
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 com.gmail.nossr50.util.MetadataConstants;
|
||||||
import org.bukkit.block.BlockFace;
|
import org.bukkit.block.BlockFace;
|
||||||
import org.bukkit.entity.Arrow;
|
import org.bukkit.entity.Arrow;
|
||||||
|
import org.bukkit.metadata.FixedMetadataValue;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
import org.bukkit.util.Vector;
|
import org.bukkit.util.Vector;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
@ -42,5 +44,37 @@ public class ProjectileUtils {
|
|||||||
if(arrow.hasMetadata(MetadataConstants.METADATA_KEY_SPAWNED_ARROW)) {
|
if(arrow.hasMetadata(MetadataConstants.METADATA_KEY_SPAWNED_ARROW)) {
|
||||||
arrow.removeMetadata(MetadataConstants.METADATA_KEY_SPAWNED_ARROW, mcMMO.p);
|
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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user