From b5c03a56e435004d3218fbf5d0402abd104fa05b Mon Sep 17 00:00:00 2001 From: Genny Date: Tue, 16 Jun 2020 15:33:43 -0500 Subject: Complete revamp of the damage system --- README.md | 14 ++--- pom.xml | 2 +- src/main/java/dev/genbyte/sunfright/Damager.java | 74 +++++++++++++++--------- 3 files changed, 53 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index 5d53542..27ff2f0 100644 --- a/README.md +++ b/README.md @@ -34,8 +34,8 @@ to break on the default damage value. Data is pulled from the [mcwiki-helmets]: https://minecraft.gamepedia.com/Helmet#Durability ## Damage Conditions -You will be damaged if you are in skylight greater than 3 and it is not during -this time of day. +You will be damaged if you are in direct sunlight and not under a solid block +(or black stained glass) and the time falls in any of these ranges: | Weather Condition | Time Start/End | Clock Start/End | | ----------------- | -------------- | --------------- | @@ -44,12 +44,10 @@ this time of day. | Thunder Storm | 12299 - 23699 | ![](docs/thunder_safe.png) | In addition to these conditions, your helmet may not take damage if you have -Unbreaking or a level of Fire Protection higher than 1. There is a -`(60 + (40 รท (Unbreaking level + Fire Protection level) ) )%` chance that your -helmet will take damage. Which means if you have Fire Protection I and -Unbreaking III, there is a 30% chance your helmet won't take damage. With -Fire Protection IV and Unbreaking III, there is a 35% chance your helmet won't -take damage. +a Fire Protection level higher than I. If you do, then the extra Fire Protection +levels act as Unbreaking. So if you have Fire Protection IV, then it is +equivalent to Unbreaking III and the sun has a 30% chance to not damage your +helmet. Fire Protection III has a 27% chance to not damage, and II a 20%. ### Notes - Respawn helmets disappear when you are safe. diff --git a/pom.xml b/pom.xml index da0d501..6404dfa 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ dev.genbyte.sunfright sunfright jar - 0.6.2 + 0.7.0 sunfright Burn me to a crisp, large glowing orb! diff --git a/src/main/java/dev/genbyte/sunfright/Damager.java b/src/main/java/dev/genbyte/sunfright/Damager.java index c3bbe44..038295d 100644 --- a/src/main/java/dev/genbyte/sunfright/Damager.java +++ b/src/main/java/dev/genbyte/sunfright/Damager.java @@ -2,7 +2,6 @@ package dev.genbyte.sunfright; import java.util.Collection; import java.util.Random; -import java.util.logging.Level; import org.bukkit.Location; import org.bukkit.Material; @@ -14,8 +13,6 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.Damageable; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.scheduler.BukkitRunnable; -import org.bukkit.util.RayTraceResult; -import org.bukkit.util.Vector; public class Damager extends BukkitRunnable { private final Sunfright sf; @@ -27,18 +24,40 @@ public class Damager extends BukkitRunnable { } public void run() { + if (!timeShouldDamage()) { + return; + } + World sunnedWorld = sf.sunnedWorld; Collection players = sunnedWorld.getPlayers(); players.forEach((player) -> { - byte skylight = player.getLocation().getBlock().getLightFromSky(); + Location loc = player.getLocation(); + int x = loc.getBlockX(); + int y = loc.getBlockY(); + int z = loc.getBlockZ(); + // Returns one lower than it should? + int highestY = sunnedWorld.getHighestBlockAt(loc).getLocation().getBlockY()+1; + + for (int i = y; i < highestY; ++i) { + Block current = sunnedWorld.getBlockAt(x, i, z); + + if (!blockShouldDamage(current.getType())) { + /* player rulled to be safe. Remove their helmet if it's the one we gave, but + only do so if the skylight is less than three. This will keep us from + removing the starter helmet if they're just chopping down a tree */ + if (player.getInventory().getHelmet() != null && + player.getLocation().getBlock().getLightFromSky() > 3 && + player.getInventory().getHelmet().getEnchantmentLevel(Enchantment.VANISHING_CURSE) == 2) + { + player.getInventory().setHelmet(new ItemStack(Material.AIR)); + } - if (skylight > 3 && timeShouldDamage()) { - new DoDamage(player, sf.damagaPerSecond).runTask(sf); - } else if (player.getInventory().getHelmet() != null - && player.getInventory().getHelmet().getEnchantmentLevel(Enchantment.VANISHING_CURSE) == 2) { - player.getInventory().setHelmet(new ItemStack(Material.AIR)); + return; + } } + + new DoDamage(player, sf.damagaPerSecond).runTask(sf); }); } @@ -66,6 +85,23 @@ public class Damager extends BukkitRunnable { return true; } + /* + Material.isTransparent() is buggy and awful and only gives true for some things. This function + checks if a material lets light pass and should damage the player. + I've never seen it give a false positive, only a false negative, so it is one of the first + things we check. + */ + @SuppressWarnings("deprecation") + private boolean blockShouldDamage(Material mat) { + String key = mat.getKey().getKey().toLowerCase(); + + if (mat == Material.BLACK_STAINED_GLASS) { + return false; + } + + return mat.isTransparent() || key.indexOf("glass") != -1 || key.indexOf("leaves") != -1 || key.indexOf("sign") != -1 || key.indexOf("trapdoor") != -1 || key.indexOf("fence") != -1 || key.indexOf("bed") != -1 || mat == Material.ICE || mat == Material.HOPPER || mat == Material.COBWEB; + } + private class DoDamage extends BukkitRunnable { private final Player player; private final int damage; @@ -76,23 +112,6 @@ public class Damager extends BukkitRunnable { } public void run() { - Location loc = player.getLocation(); - World world = loc.getWorld(); - RayTraceResult rtr = player.getWorld().rayTraceBlocks( - loc, - new Vector(0, 1, 0), - world.getMaxHeight()-loc.getY() - ); - - if (rtr != null) { - Block topBlock = rtr.getHitBlock(); - if (topBlock != null && topBlock.getLocation().getY() > player.getLocation().getY() - && topBlock.getType().equals(Material.BLACK_STAINED_GLASS) - ) { - return; - } - } - ItemStack helmet = player.getInventory().getHelmet(); if (helmet != null) { @@ -102,7 +121,6 @@ public class Damager extends BukkitRunnable { Damageable helmetDamageable = (Damageable) helmetMeta; int helmetDamage = helmetDamageable.getDamage(); int fireProtLevel = helmet.getEnchantmentLevel(Enchantment.PROTECTION_FIRE); - int unbrLevel = helmet.getEnchantmentLevel(Enchantment.DURABILITY); if (fireProtLevel < 1) { damagePlayer(); @@ -127,7 +145,7 @@ public class Damager extends BukkitRunnable { // Formula from https://minecraft.gamepedia.com/Unbreaking // Origintal is 60 + (40 / (level+1)) but we subtract one from fireProtLevel // so the +1 cancels - int chanceToDamage = 60 + (40 / (fireProtLevel+unbrLevel)); + int chanceToDamage = 60 + (40 / (fireProtLevel)); if (rand.nextInt(99)+1 <= chanceToDamage) { helmetDamageable.setDamage(helmetDamage + (damage/2)); -- cgit 1.4.1-3-g733a5