package WayofTime.bloodmagic.ritual; import java.util.ArrayList; import java.util.List; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.init.MobEffects; import net.minecraft.potion.PotionEffect; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; import WayofTime.bloodmagic.api.BloodMagicAPI; import WayofTime.bloodmagic.api.Constants; import WayofTime.bloodmagic.api.ritual.AreaDescriptor; import WayofTime.bloodmagic.api.ritual.EnumRuneType; import WayofTime.bloodmagic.api.ritual.IMasterRitualStone; import WayofTime.bloodmagic.api.ritual.Ritual; import WayofTime.bloodmagic.api.ritual.RitualComponent; import WayofTime.bloodmagic.api.saving.SoulNetwork; import WayofTime.bloodmagic.api.soul.DemonWillHolder; import WayofTime.bloodmagic.api.soul.EnumDemonWillType; import WayofTime.bloodmagic.api.util.helper.NetworkHelper; import WayofTime.bloodmagic.demonAura.WorldDemonWillHandler; import WayofTime.bloodmagic.registry.ModPotions; import WayofTime.bloodmagic.util.Utils; public class RitualLava extends Ritual { public static final String LAVA_RANGE = "lavaRange"; public static final String FIRE_FUSE_RANGE = "fireFuse"; public static final String FIRE_RESIST_RANGE = "fireResist"; public static final String FIRE_DAMAGE_RANGE = "fireDamage"; public static final double vengefulWillDrain = 1; public static final double steadfastWillDrain = 0.5; public static final double corrosiveWillDrain = 0.2; public int timer = 0; public static final int corrosiveRefreshTime = 20; public RitualLava() { super("ritualLava", 0, 10000, "ritual." + Constants.Mod.MODID + ".lavaRitual"); addBlockRange(LAVA_RANGE, new AreaDescriptor.Rectangle(new BlockPos(0, 1, 0), 1)); addBlockRange(FIRE_FUSE_RANGE, new AreaDescriptor.Rectangle(new BlockPos(-2, -2, -2), 5)); addBlockRange(FIRE_RESIST_RANGE, new AreaDescriptor.Rectangle(new BlockPos(0, 0, 0), 1)); addBlockRange(FIRE_DAMAGE_RANGE, new AreaDescriptor.Rectangle(new BlockPos(0, 0, 0), 1)); setMaximumVolumeAndDistanceOfRange(LAVA_RANGE, 9, 3, 3); setMaximumVolumeAndDistanceOfRange(FIRE_FUSE_RANGE, 0, 10, 10); setMaximumVolumeAndDistanceOfRange(FIRE_RESIST_RANGE, 0, 10, 10); setMaximumVolumeAndDistanceOfRange(FIRE_DAMAGE_RANGE, 0, 10, 10); } @Override public void performRitual(IMasterRitualStone masterRitualStone) { timer++; World world = masterRitualStone.getWorldObj(); SoulNetwork network = NetworkHelper.getSoulNetwork(masterRitualStone.getOwner()); int currentEssence = network.getCurrentEssence(); int lpDrain = 0; if (currentEssence < getRefreshCost()) { network.causeNausea(); return; } BlockPos pos = masterRitualStone.getBlockPos(); List willConfig = masterRitualStone.getActiveWillConfig(); double rawWill = this.getWillRespectingConfig(world, pos, EnumDemonWillType.DEFAULT, willConfig); double rawDrained = 0; DemonWillHolder holder = WorldDemonWillHandler.getWillHolder(world, pos); AreaDescriptor lavaRange = getBlockRange(LAVA_RANGE); int maxLavaVolume = getMaxVolumeForRange(LAVA_RANGE, willConfig, holder); if (!lavaRange.isWithinRange(getMaxVerticalRadiusForRange(LAVA_RANGE, willConfig, holder), getMaxHorizontalRadiusForRange(LAVA_RANGE, willConfig, holder)) || (maxLavaVolume != 0 && lavaRange.getVolume() > maxLavaVolume)) { return; } for (BlockPos newPos : lavaRange.getContainedPositions(pos)) { IBlockState state = world.getBlockState(newPos); if (world.isAirBlock(newPos) || Utils.isFlowingLiquid(world, newPos, state)) { int lpCost = getLPCostForRawWill(rawWill); if (currentEssence < lpCost) { break; } world.setBlockState(newPos, Blocks.FLOWING_LAVA.getDefaultState()); currentEssence -= lpCost; lpDrain += lpCost; if (rawWill > 0) { double drain = getWillCostForRawWill(rawWill); rawWill -= drain; rawDrained += drain; } } } double vengefulWill = this.getWillRespectingConfig(world, pos, EnumDemonWillType.VENGEFUL, willConfig); double steadfastWill = this.getWillRespectingConfig(world, pos, EnumDemonWillType.STEADFAST, willConfig); double corrosiveWill = this.getWillRespectingConfig(world, pos, EnumDemonWillType.CORROSIVE, willConfig); if (vengefulWill >= vengefulWillDrain) { double vengefulDrained = 0; AreaDescriptor fuseRange = getBlockRange(FIRE_FUSE_RANGE); AxisAlignedBB fuseArea = fuseRange.getAABB(pos); List entities = world.getEntitiesWithinAABB(EntityLivingBase.class, fuseArea); for (EntityLivingBase entity : entities) { if (vengefulWill < vengefulWillDrain) { break; } if (entity instanceof EntityPlayer) { continue; } if (!entity.isPotionActive(ModPotions.fireFuse)) { entity.addPotionEffect(new PotionEffect(ModPotions.fireFuse, 100, 0)); vengefulDrained += vengefulWillDrain; vengefulWill -= vengefulWillDrain; } } if (vengefulDrained > 0) { WorldDemonWillHandler.drainWill(world, pos, EnumDemonWillType.VENGEFUL, vengefulDrained, true); } } if (steadfastWill >= steadfastWillDrain) { double steadfastDrained = 0; AreaDescriptor resistRange = getBlockRange(FIRE_RESIST_RANGE); int duration = getFireResistForWill(steadfastWill); AxisAlignedBB resistArea = resistRange.getAABB(pos); List entities = world.getEntitiesWithinAABB(EntityPlayer.class, resistArea); for (EntityPlayer entity : entities) { if (steadfastWill < steadfastWillDrain) { break; } if (!entity.isPotionActive(MobEffects.FIRE_RESISTANCE) || (entity.getActivePotionEffect(MobEffects.FIRE_RESISTANCE).getDuration() < 2)) { entity.addPotionEffect(new PotionEffect(MobEffects.FIRE_RESISTANCE, 100, 0)); steadfastDrained += steadfastWillDrain; steadfastWill -= steadfastWillDrain; } } if (steadfastDrained > 0) { WorldDemonWillHandler.drainWill(world, pos, EnumDemonWillType.STEADFAST, steadfastDrained, true); } } if (timer % corrosiveRefreshTime == 0 && corrosiveWill >= corrosiveWillDrain) { double corrosiveDrained = 0; AreaDescriptor resistRange = getBlockRange(FIRE_DAMAGE_RANGE); float damage = getCorrosiveDamageForWill(corrosiveWill); AxisAlignedBB damageArea = resistRange.getAABB(pos); List entities = world.getEntitiesWithinAABB(EntityLivingBase.class, damageArea); for (EntityLivingBase entity : entities) { if (corrosiveWill < corrosiveWillDrain) { break; } if (!entity.isDead && entity.hurtTime <= 0 && Utils.isImmuneToFireDamage(entity)) { if (entity.attackEntityFrom(BloodMagicAPI.getDamageSource(), damage)) { corrosiveDrained += corrosiveWillDrain; corrosiveWill -= corrosiveWillDrain; } } } if (corrosiveDrained > 0) { WorldDemonWillHandler.drainWill(world, pos, EnumDemonWillType.CORROSIVE, corrosiveDrained, true); } } if (rawDrained > 0) { WorldDemonWillHandler.drainWill(world, pos, EnumDemonWillType.DEFAULT, rawDrained, true); } network.syphon(lpDrain); } @Override public int getRefreshTime() { return 1; } @Override public int getRefreshCost() { return 500; } @Override public ITextComponent[] provideInformationOfRitualToPlayer(EntityPlayer player) { return new ITextComponent[] { new TextComponentTranslation(this.getUnlocalizedName() + ".info"), new TextComponentTranslation(this.getUnlocalizedName() + ".default.info"), new TextComponentTranslation(this.getUnlocalizedName() + ".corrosive.info"), new TextComponentTranslation(this.getUnlocalizedName() + ".steadfast.info"), new TextComponentTranslation(this.getUnlocalizedName() + ".destructive.info"), new TextComponentTranslation(this.getUnlocalizedName() + ".vengeful.info") }; } @Override public ArrayList getComponents() { ArrayList components = new ArrayList(); this.addParallelRunes(components, 1, 0, EnumRuneType.FIRE); return components; } @Override public Ritual getNewCopy() { return new RitualLava(); } @Override public int getMaxVolumeForRange(String range, List activeTypes, DemonWillHolder holder) { if (LAVA_RANGE.equals(range) && activeTypes.contains(EnumDemonWillType.DESTRUCTIVE)) { double destructiveWill = holder.getWill(EnumDemonWillType.DESTRUCTIVE); if (destructiveWill > 0) { return 9 + (int) Math.pow(destructiveWill / 10, 1.5); } } return volumeRangeMap.get(range); } @Override public int getMaxVerticalRadiusForRange(String range, List activeTypes, DemonWillHolder holder) { if (LAVA_RANGE.equals(range) && activeTypes.contains(EnumDemonWillType.DESTRUCTIVE)) { double destructiveWill = holder.getWill(EnumDemonWillType.DESTRUCTIVE); if (destructiveWill > 0) { return (int) (3 + destructiveWill / 10d); } } return verticalRangeMap.get(range); } @Override public int getMaxHorizontalRadiusForRange(String range, List activeTypes, DemonWillHolder holder) { if (LAVA_RANGE.equals(range) && activeTypes.contains(EnumDemonWillType.DESTRUCTIVE)) { double destructiveWill = holder.getWill(EnumDemonWillType.DESTRUCTIVE); if (destructiveWill > 0) { return (int) (3 + destructiveWill / 10d); } } return horizontalRangeMap.get(range); } public int getFireResistForWill(double steadfastWill) { return (int) (200 + steadfastWill * 3); } public float getCorrosiveDamageForWill(double corrosiveWill) { return (float) (1 + corrosiveWill * 0.05); } public int getLPCostForRawWill(double raw) { return Math.max((int) (500 - raw), 0); } public double getWillCostForRawWill(double raw) { return Math.min(1, raw / 500); } }