diff --git a/src/main/java/electroblob/wizardry/spell/Decay.java b/src/main/java/electroblob/wizardry/spell/Decay.java index afca662c..119b7b79 100644 --- a/src/main/java/electroblob/wizardry/spell/Decay.java +++ b/src/main/java/electroblob/wizardry/spell/Decay.java @@ -37,7 +37,7 @@ public class Decay extends SpellConstructRanged { int verticalRange = (int)(6 * modifiers.get(WizardryItems.blast_upgrade)); for(int i=0; iThe number of operations performed by this method is proportional to the square of this + * parameter, so for performance reasons it is recommended that it does not exceed around 10. + * @param verticalRange The maximum number of blocks on the y axis the returned position can be from the given + * position. + * @param lineOfSight Whether to require line-of-sight from the origin to the returned position. + * @return A BlockPos with the coordinates of the block directly above the ground at the position found, or null if + * none were found within range. Importantly, since this method checks all possible positions within + * range (i.e. randomness only occurs when deciding between the possible positions), if it returns null once + * then it will always return null given the same circumstances and parameters. What this means is that you + * can (and should) immediately stop trying to cast a summoning spell if this returns null. + */ + @Nullable + public static BlockPos findNearbyFloorSpace(World world, BlockPos origin, int horizontalRange, int verticalRange, boolean lineOfSight){ List possibleLocations = new ArrayList(); + final Vec3d centre = WizardryUtilities.getCentre(origin); + for(int x = -horizontalRange; x <= horizontalRange; x++){ for(int z = -horizontalRange; z <= horizontalRange; z++){ + Integer y = WizardryUtilities.getNearestFloor(world, origin.add(x, 0, z), verticalRange); - if(y != null) possibleLocations.add(new BlockPos(origin.getX() + x, y, origin.getZ() + z)); + + if(y != null){ + + BlockPos location = new BlockPos(origin.getX() + x, y, origin.getZ() + z); + + if(lineOfSight){ + // Since we're only using finding collidable surfaces, it doesn't make much sense to include + // non-collidable blocks here! + RayTraceResult rayTrace = world.rayTraceBlocks(centre, WizardryUtilities.getCentre(location), + false, true, false); + if(rayTrace != null && rayTrace.typeOfHit == RayTraceResult.Type.BLOCK) continue; + } + + possibleLocations.add(location); + } } }