mirror of
https://github.com/mcMMO-Dev/mcMMO.git
synced 2024-11-24 06:06:45 +01:00
Refactor ricochet code, don't reflect shallow angles
This commit is contained in:
parent
afff3b4c50
commit
76d4b50554
@ -1,4 +1,6 @@
|
|||||||
Version 2.2.000
|
Version 2.2.000
|
||||||
|
TODO: Trickshot: locale, multiple bounces, does not hurt yourself or allies, reduced damage per bounce?
|
||||||
|
TODO: Add metadata cleanup unit tests
|
||||||
TODO: Cleanup new arrow metadatas
|
TODO: Cleanup new arrow metadatas
|
||||||
TODO: SQL DB update
|
TODO: SQL DB update
|
||||||
TODO: SQL unit tests
|
TODO: SQL unit tests
|
||||||
|
@ -35,7 +35,7 @@ public enum SubSkillType {
|
|||||||
/* CROSSBOWS */
|
/* CROSSBOWS */
|
||||||
CROSSBOWS_SUPER_SHOTGUN(1),
|
CROSSBOWS_SUPER_SHOTGUN(1),
|
||||||
CROSSBOWS_CROSSBOWS_LIMIT_BREAK(10),
|
CROSSBOWS_CROSSBOWS_LIMIT_BREAK(10),
|
||||||
CROSSBOWS_TRICK_SHOT(5),
|
CROSSBOWS_TRICK_SHOT(3),
|
||||||
|
|
||||||
/* Excavation */
|
/* Excavation */
|
||||||
EXCAVATION_ARCHAEOLOGY(8),
|
EXCAVATION_ARCHAEOLOGY(8),
|
||||||
|
@ -15,6 +15,7 @@ import com.gmail.nossr50.metadata.MobMetadataService;
|
|||||||
import com.gmail.nossr50.party.PartyManager;
|
import com.gmail.nossr50.party.PartyManager;
|
||||||
import com.gmail.nossr50.runnables.TravelingBlockMetaCleanup;
|
import com.gmail.nossr50.runnables.TravelingBlockMetaCleanup;
|
||||||
import com.gmail.nossr50.skills.archery.Archery;
|
import com.gmail.nossr50.skills.archery.Archery;
|
||||||
|
import com.gmail.nossr50.skills.crossbows.Crossbows;
|
||||||
import com.gmail.nossr50.skills.mining.BlastMining;
|
import com.gmail.nossr50.skills.mining.BlastMining;
|
||||||
import com.gmail.nossr50.skills.mining.MiningManager;
|
import com.gmail.nossr50.skills.mining.MiningManager;
|
||||||
import com.gmail.nossr50.skills.taming.Taming;
|
import com.gmail.nossr50.skills.taming.Taming;
|
||||||
@ -28,7 +29,10 @@ import com.gmail.nossr50.util.skills.CombatUtils;
|
|||||||
import com.gmail.nossr50.util.skills.ProjectileUtils;
|
import com.gmail.nossr50.util.skills.ProjectileUtils;
|
||||||
import com.gmail.nossr50.worldguard.WorldGuardManager;
|
import com.gmail.nossr50.worldguard.WorldGuardManager;
|
||||||
import com.gmail.nossr50.worldguard.WorldGuardUtils;
|
import com.gmail.nossr50.worldguard.WorldGuardUtils;
|
||||||
import org.bukkit.*;
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.NamespacedKey;
|
||||||
|
import org.bukkit.OfflinePlayer;
|
||||||
import org.bukkit.attribute.Attribute;
|
import org.bukkit.attribute.Attribute;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.enchantments.Enchantment;
|
import org.bukkit.enchantments.Enchantment;
|
||||||
@ -48,9 +52,6 @@ import org.bukkit.potion.PotionEffectType;
|
|||||||
import org.bukkit.projectiles.ProjectileSource;
|
import org.bukkit.projectiles.ProjectileSource;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import static com.gmail.nossr50.util.skills.ProjectileUtils.getNormal;
|
|
||||||
import static com.gmail.nossr50.util.skills.ProjectileUtils.spawnReflectedArrow;
|
|
||||||
|
|
||||||
public class EntityListener implements Listener {
|
public class EntityListener implements Listener {
|
||||||
private final mcMMO pluginRef;
|
private final mcMMO pluginRef;
|
||||||
private final @NotNull MobMetadataService mobMetadataService;
|
private final @NotNull MobMetadataService mobMetadataService;
|
||||||
@ -411,7 +412,7 @@ public class EntityListener implements Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(entityDamageEvent.getDamager() instanceof Projectile) {
|
if(entityDamageEvent.getDamager() instanceof Projectile) {
|
||||||
CombatUtils.cleanupArrowMetadata((Projectile) entityDamageEvent.getDamager());
|
ProjectileUtils.cleanupProjectileMetadata((Projectile) entityDamageEvent.getDamager());
|
||||||
}
|
}
|
||||||
|
|
||||||
if(entityDamageEvent.getEntity() instanceof Player player && entityDamageEvent.getDamager() instanceof Player) {
|
if(entityDamageEvent.getEntity() instanceof Player player && entityDamageEvent.getDamager() instanceof Player) {
|
||||||
@ -1118,17 +1119,6 @@ public class EntityListener implements Listener {
|
|||||||
if (WorldBlacklist.isWorldBlacklisted(event.getEntity().getWorld()))
|
if (WorldBlacklist.isWorldBlacklisted(event.getEntity().getWorld()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(event.getEntity() instanceof Arrow originalArrow && event.getHitBlock() != null && event.getHitBlockFace() != null) {
|
Crossbows.processCrossbows(event, pluginRef);
|
||||||
if (originalArrow.getShooter() instanceof Player) {
|
|
||||||
// Avoid infinite spawning of arrows
|
|
||||||
if (originalArrow.hasMetadata(MetadataConstants.METADATA_KEY_SPAWNED_ARROW)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Spawn a new arrow shooting in the reflected direction
|
|
||||||
spawnReflectedArrow(pluginRef, originalArrow, originalArrow.getLocation(),
|
|
||||||
getNormal(event.getHitBlockFace()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
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;
|
||||||
|
import org.bukkit.event.entity.ProjectileHitEvent;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
|
||||||
|
import static com.gmail.nossr50.util.skills.ProjectileUtils.getNormal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Util class for crossbows.
|
||||||
|
*/
|
||||||
|
public class Crossbows {
|
||||||
|
public static void processCrossbows(ProjectileHitEvent event, Plugin pluginRef) {
|
||||||
|
if(event.getEntity() instanceof Arrow originalArrow && event.getHitBlock() != null && event.getHitBlockFace() != null) {
|
||||||
|
if (originalArrow.getShooter() instanceof Player) {
|
||||||
|
// Avoid infinite spawning of arrows
|
||||||
|
if (originalArrow.hasMetadata(MetadataConstants.METADATA_KEY_SPAWNED_ARROW)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
McMMOPlayer mmoPlayer = UserManager.getPlayer((Player) originalArrow.getShooter());
|
||||||
|
if (mmoPlayer != null) {
|
||||||
|
mmoPlayer.getCrossbowsManager().handleRicochet(
|
||||||
|
pluginRef,
|
||||||
|
originalArrow,
|
||||||
|
getNormal(event.getHitBlockFace()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,9 +3,49 @@ 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.skills.SkillManager;
|
import com.gmail.nossr50.skills.SkillManager;
|
||||||
|
import com.gmail.nossr50.util.MetadataConstants;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.entity.Arrow;
|
||||||
|
import org.bukkit.metadata.FixedMetadataValue;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
import org.bukkit.projectiles.ProjectileSource;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void handleRicochet(@NotNull Plugin pluginRef, @NotNull Arrow originalArrow, @NotNull Vector hitBlockNormal) {
|
||||||
|
// Reflect arrow in new direction
|
||||||
|
// cleanup metadata on original arrow
|
||||||
|
// TODO: Add an event for this for plugins to hook into
|
||||||
|
spawnReflectedArrow(pluginRef, originalArrow, originalArrow.getLocation(), hitBlockNormal);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void spawnReflectedArrow(@NotNull Plugin pluginRef, @NotNull Arrow originalArrow, @NotNull Location origin, @NotNull Vector normal) {
|
||||||
|
final ProjectileSource originalArrowShooter = originalArrow.getShooter();
|
||||||
|
final Vector arrowInBlockVector = originalArrow.getVelocity();
|
||||||
|
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
|
||||||
|
if (arrowInBlockVector.angle(inverseNormal) < Math.PI / 4) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Spawn new arrow with the reflected direction
|
||||||
|
Arrow arrow = originalArrow.getWorld().spawnArrow(origin,
|
||||||
|
reflectedDirection, 1, 1);
|
||||||
|
arrow.setShooter(originalArrowShooter);
|
||||||
|
arrow.setMetadata(MetadataConstants.METADATA_KEY_SPAWNED_ARROW,
|
||||||
|
new FixedMetadataValue(pluginRef, originalArrowShooter));
|
||||||
|
|
||||||
|
// TODO: This metadata needs to get cleaned up at some point
|
||||||
|
arrow.setMetadata(MetadataConstants.METADATA_KEY_BOW_TYPE,
|
||||||
|
new FixedMetadataValue(pluginRef, originalArrow.getMetadata(
|
||||||
|
MetadataConstants.METADATA_KEY_BOW_TYPE).get(0)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -161,16 +161,10 @@ public final class CombatUtils {
|
|||||||
|
|
||||||
//Make sure the profiles been loaded
|
//Make sure the profiles been loaded
|
||||||
if(mcMMOPlayer == null) {
|
if(mcMMOPlayer == null) {
|
||||||
cleanupArrowMetadata(arrow);
|
ProjectileUtils.cleanupProjectileMetadata(arrow);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// CrossbowsManager crossbowsManager = mcMMOPlayer.getCrossbowsManager();
|
|
||||||
|
|
||||||
// if (crossbowsManager.canActivateAbility()) {
|
|
||||||
// mcMMOPlayer.checkAbilityActivation(PrimarySkillType.CROSSBOWS);
|
|
||||||
// }
|
|
||||||
|
|
||||||
double boostedDamage = event.getDamage();
|
double boostedDamage = event.getDamage();
|
||||||
|
|
||||||
if(canUseLimitBreak(player, target, SubSkillType.CROSSBOWS_CROSSBOWS_LIMIT_BREAK)) {
|
if(canUseLimitBreak(player, target, SubSkillType.CROSSBOWS_CROSSBOWS_LIMIT_BREAK)) {
|
||||||
@ -190,7 +184,7 @@ public final class CombatUtils {
|
|||||||
"Final Damage: "+boostedDamage);
|
"Final Damage: "+boostedDamage);
|
||||||
|
|
||||||
//Clean data
|
//Clean data
|
||||||
cleanupArrowMetadata(arrow);
|
ProjectileUtils.cleanupProjectileMetadata(arrow);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void processAxeCombat(@NotNull LivingEntity target, @NotNull Player player, @NotNull EntityDamageByEntityEvent event) {
|
private static void processAxeCombat(@NotNull LivingEntity target, @NotNull Player player, @NotNull EntityDamageByEntityEvent event) {
|
||||||
@ -327,7 +321,7 @@ public final class CombatUtils {
|
|||||||
|
|
||||||
//Make sure the profiles been loaded
|
//Make sure the profiles been loaded
|
||||||
if(mcMMOPlayer == null) {
|
if(mcMMOPlayer == null) {
|
||||||
cleanupArrowMetadata(arrow);
|
ProjectileUtils.cleanupProjectileMetadata(arrow);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -368,7 +362,7 @@ public final class CombatUtils {
|
|||||||
"Initial Damage: "+initialDamage,
|
"Initial Damage: "+initialDamage,
|
||||||
"Final Damage: "+boostedDamage);
|
"Final Damage: "+boostedDamage);
|
||||||
//Clean data
|
//Clean data
|
||||||
cleanupArrowMetadata(arrow);
|
ProjectileUtils.cleanupProjectileMetadata(arrow);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -500,7 +494,7 @@ public final class CombatUtils {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//Cleanup Arrow
|
//Cleanup Arrow
|
||||||
cleanupArrowMetadata(arrow);
|
ProjectileUtils.cleanupProjectileMetadata(arrow);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target.getType() != EntityType.CREEPER
|
if (target.getType() != EntityType.CREEPER
|
||||||
@ -733,35 +727,6 @@ public final class CombatUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dealNoInvulnerabilityTickDamage(target, damage, attacker);
|
dealNoInvulnerabilityTickDamage(target, damage, attacker);
|
||||||
|
|
||||||
// //IFrame storage
|
|
||||||
//// int noDamageTicks = target.getNoDamageTicks();
|
|
||||||
//
|
|
||||||
//// String debug = "BLEED DMG RESULT: INC DMG:"+damage+", HP-Before:"+target.getHealth()+", HP-After:";
|
|
||||||
//
|
|
||||||
//// double incDmg = getFakeDamageFinalResult(attacker, target, DamageCause.ENTITY_ATTACK, damage);
|
|
||||||
//
|
|
||||||
//// double newHealth = Math.max(0, target.getHealth() - incDmg);
|
|
||||||
//
|
|
||||||
// //Don't kill things with a stone or wooden weapon
|
|
||||||
//// if(toolTier < 3 && newHealth == 0)
|
|
||||||
//// return;
|
|
||||||
//
|
|
||||||
// target.setMetadata(mcMMO.CUSTOM_DAMAGE_METAKEY, mcMMO.metadataValue);
|
|
||||||
//
|
|
||||||
// if(newHealth == 0 && !(target instanceof Player))
|
|
||||||
// {
|
|
||||||
// target.damage(99999, attacker);
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
//// Vector beforeRuptureVec = new Vector(target.getVelocity().getX(), target.getVelocity().getY(), target.getVelocity().getZ()); ;
|
|
||||||
// target.damage(damage, attacker);
|
|
||||||
//// debug+=target.getHealth();
|
|
||||||
// Bukkit.broadcastMessage(debug);
|
|
||||||
//// target.setNoDamageTicks(noDamageTicks); //Do not add additional IFrames
|
|
||||||
//// target.setVelocity(beforeRuptureVec);
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1062,31 +1027,12 @@ public final class CombatUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Clean up metadata from a projectile
|
|
||||||
*
|
|
||||||
* @param entity projectile
|
|
||||||
*/
|
|
||||||
public static void cleanupArrowMetadata(@NotNull Projectile entity) {
|
|
||||||
if(entity.hasMetadata(MetadataConstants.METADATA_KEY_INF_ARROW)) {
|
|
||||||
entity.removeMetadata(MetadataConstants.METADATA_KEY_INF_ARROW, mcMMO.p);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(entity.hasMetadata(MetadataConstants.METADATA_KEY_BOW_FORCE)) {
|
|
||||||
entity.removeMetadata(MetadataConstants.METADATA_KEY_BOW_FORCE, mcMMO.p);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(entity.hasMetadata(MetadataConstants.METADATA_KEY_ARROW_DISTANCE)) {
|
|
||||||
entity.removeMetadata(MetadataConstants.METADATA_KEY_ARROW_DISTANCE, mcMMO.p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clean up metadata from a projectile after a minute has passed
|
* Clean up metadata from a projectile after a minute has passed
|
||||||
*
|
*
|
||||||
* @param entity the projectile
|
* @param entity the projectile
|
||||||
*/
|
*/
|
||||||
public static void delayArrowMetaCleanup(@NotNull Projectile entity) {
|
public static void delayArrowMetaCleanup(@NotNull Projectile entity) {
|
||||||
mcMMO.p.getFoliaLib().getImpl().runLater(() -> cleanupArrowMetadata(entity), 20*60);
|
mcMMO.p.getFoliaLib().getImpl().runLater(() -> ProjectileUtils.cleanupProjectileMetadata(entity), 20*60);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
package com.gmail.nossr50.util.skills;
|
package com.gmail.nossr50.util.skills;
|
||||||
|
|
||||||
|
import com.gmail.nossr50.mcMMO;
|
||||||
import com.gmail.nossr50.util.MetadataConstants;
|
import com.gmail.nossr50.util.MetadataConstants;
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.block.BlockFace;
|
import org.bukkit.block.BlockFace;
|
||||||
import org.bukkit.entity.Arrow;
|
import org.bukkit.entity.Projectile;
|
||||||
import org.bukkit.metadata.FixedMetadataValue;
|
|
||||||
import org.bukkit.plugin.Plugin;
|
|
||||||
import org.bukkit.projectiles.ProjectileSource;
|
|
||||||
import org.bukkit.util.Vector;
|
import org.bukkit.util.Vector;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
public class ProjectileUtils {
|
public class ProjectileUtils {
|
||||||
public static Vector getNormal(BlockFace blockFace) {
|
public static Vector getNormal(BlockFace blockFace) {
|
||||||
@ -22,21 +20,31 @@ public class ProjectileUtils {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void spawnReflectedArrow(Plugin pluginRef, Arrow originalArrow, Location origin, Vector normal) {
|
/**
|
||||||
// TODO: Add an event for this for plugins to hook into
|
* Clean up all possible mcMMO related metadata for a projectile
|
||||||
ProjectileSource originalArrowShooter = originalArrow.getShooter();
|
*
|
||||||
Vector incomingDirection = originalArrow.getVelocity();
|
* @param entity projectile
|
||||||
Vector reflectedDirection = incomingDirection.subtract(normal.multiply(2 * incomingDirection.dot(normal)));
|
*/
|
||||||
|
// TODO: Add test
|
||||||
|
public static void cleanupProjectileMetadata(@NotNull Projectile entity) {
|
||||||
|
if(entity.hasMetadata(MetadataConstants.METADATA_KEY_INF_ARROW)) {
|
||||||
|
entity.removeMetadata(MetadataConstants.METADATA_KEY_INF_ARROW, mcMMO.p);
|
||||||
|
}
|
||||||
|
|
||||||
// Spawn new arrow with the reflected direction
|
if(entity.hasMetadata(MetadataConstants.METADATA_KEY_BOW_FORCE)) {
|
||||||
Arrow arrow = originalArrow.getWorld().spawnArrow(origin,
|
entity.removeMetadata(MetadataConstants.METADATA_KEY_BOW_FORCE, mcMMO.p);
|
||||||
reflectedDirection, 1, 1);
|
}
|
||||||
arrow.setShooter(originalArrowShooter);
|
|
||||||
arrow.setMetadata(MetadataConstants.METADATA_KEY_SPAWNED_ARROW,
|
if(entity.hasMetadata(MetadataConstants.METADATA_KEY_ARROW_DISTANCE)) {
|
||||||
new FixedMetadataValue(pluginRef, originalArrowShooter));
|
entity.removeMetadata(MetadataConstants.METADATA_KEY_ARROW_DISTANCE, mcMMO.p);
|
||||||
// TODO: This metadata needs to get cleaned up at some point
|
}
|
||||||
arrow.setMetadata(MetadataConstants.METADATA_KEY_BOW_TYPE,
|
|
||||||
new FixedMetadataValue(pluginRef, originalArrow.getMetadata(
|
if(entity.hasMetadata(MetadataConstants.METADATA_KEY_BOW_TYPE)) {
|
||||||
MetadataConstants.METADATA_KEY_BOW_TYPE).get(0)));
|
entity.removeMetadata(MetadataConstants.METADATA_KEY_BOW_TYPE, mcMMO.p);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(entity.hasMetadata(MetadataConstants.METADATA_KEY_SPAWNED_ARROW)) {
|
||||||
|
entity.removeMetadata(MetadataConstants.METADATA_KEY_SPAWNED_ARROW, mcMMO.p);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user