- Made it so peaceful animals provide more LP by default (to encourage creating your own farm).

- Increased the effectiveness of animals for the Gathering of the Forsaken Souls ritual by a factor of 4.
- Added the framework for the Purification Altar.
This commit is contained in:
WayofTime 2016-11-05 11:14:56 -04:00
parent da4de55c2e
commit faef980e59
14 changed files with 290 additions and 31 deletions

View file

@ -10,6 +10,9 @@ Version 2.1.0-67
- Changed the Ritual of the Feathered Knife so it respects the Tough Palms Living Armour Upgrade.
- Fixed the Ritual of the Feathered Knife so that its health threshold is percent-based.
- Made the aspected Sentient Tools drop their corresponding Will type on killing enemies.
- Made it so peaceful animals provide more LP by default (to encourage creating your own farm).
- Increased the effectiveness of animals for the Gathering of the Forsaken Souls ritual by a factor of 4.
- Added the framework for the Purification Altar.
------------------------------------------------------
Version 2.1.0-66

View file

@ -202,7 +202,7 @@ public class ConfigHandler
category = "Blood Altar Sacrificial Values";
config.addCustomCategoryComment(category, "Entity Sacrificial Value Settings");
entitySacrificeValuesList = config.getStringList("entitySacrificeValues", category, new String[] { "EntityVillager;2000", "EntitySlime;150", "EntityEnderman;200", "EntityCow;250", "EntityChicken;250", "EntityHorse;250", "EntitySheep;250", "EntityWolf;250", "EntityOcelot;250", "EntityPig;250", "EntityRabbit;250", "EntityArmorStand;0" }, "Used to edit the amount of LP gained per sacrifice of the given entity.\nSetting an entity to 0 effectively blacklists it.\nIf a mod modifies an entity via the API, it will take precedence over this config.\nSyntax: EntityClassName;LPPerSacrifice");
entitySacrificeValuesList = config.getStringList("entitySacrificeLP:HPValues", category, new String[] { "EntityVillager;100", "EntitySlime;15", "EntityEnderman;10", "EntityCow;100", "EntityChicken;100", "EntityHorse;250", "EntitySheep;100", "EntityWolf;100", "EntityOcelot;100", "EntityPig;100", "EntityRabbit;100", "EntityArmorStand;0" }, "Used to edit the amount of LP gained per HP sacrificed for the given entity.\nSetting an entity to 0 effectively blacklists it.\nIf a mod modifies an entity via the API, it will take precedence over this config.\nSyntax: EntityClassName;LPPerHP");
buildEntitySacrificeValues();
category = "Potions";

View file

@ -221,7 +221,8 @@ public class BloodMagicAPI
* @param entityClass
* - The class of the entity to blacklist.
* @param sacrificeValue
* - The Amount of LP to provide per each entity sacrificed.
* - The Amount of LP to provide per each HP of the entity
* sacrificed.
*/
public static void setEntitySacrificeValue(Class<? extends EntityLivingBase> entityClass, int sacrificeValue)
{
@ -235,7 +236,8 @@ public class BloodMagicAPI
* @param entityClassName
* - The name of the class of the entity to blacklist.
* @param sacrificeValue
* - The Amount of LP to provide per each entity sacrificed.
* - The Amount of LP to provide per each HP of the entity
* sacrificed.
*/
public static void setEntitySacrificeValue(String entityClassName, int sacrificeValue)
{

View file

@ -33,6 +33,7 @@ public class Constants
public static final String DIRECTION = "direction";
public static final String REAGENT_TANKS = "reagentTanks";
public static final String CURRENT_INCENSE = "BM:CurrentIncense";
public static final String CURRENT_PURITY = "BM:CurrentPurity";
public static final String EMPTY = "Empty";
public static final String OUTPUT_AMOUNT = "outputAmount";
public static final String INPUT_AMOUNT = "inputAmount";

View file

@ -0,0 +1,12 @@
package WayofTime.bloodmagic.api.iface;
import net.minecraft.item.ItemStack;
public interface IPurificationAsh
{
double getTotalPurity(ItemStack stack);
double getMaxPurity(ItemStack stack);
double getPurityRate(ItemStack stack);
}

View file

@ -0,0 +1,39 @@
package WayofTime.bloodmagic.api.util.helper;
import net.minecraft.entity.passive.EntityAnimal;
import net.minecraft.nbt.NBTTagCompound;
import WayofTime.bloodmagic.api.Constants;
public class PurificationHelper
{
public static double getCurrentPurity(EntityAnimal animal)
{
NBTTagCompound data = animal.getEntityData();
if (data.hasKey(Constants.NBT.CURRENT_PURITY))
{
return data.getDouble(Constants.NBT.CURRENT_PURITY);
}
return 0;
}
public static void setCurrentPurity(EntityAnimal animal, double amount)
{
NBTTagCompound data = animal.getEntityData();
data.setDouble(Constants.NBT.CURRENT_PURITY, amount);
}
public static double addPurity(EntityAnimal animal, double added, double max)
{
double currentPurity = getCurrentPurity(animal);
double newAmount = Math.min(max, currentPurity + added);
if (newAmount < max)
{
setCurrentPurity(animal, newAmount);
return newAmount - currentPurity;
}
return 0;
}
}

View file

@ -20,6 +20,10 @@ public class EntityMeteor extends EntityThrowable implements IThrowableEntity
protected int ticksInAir = 0;
protected int maxTicksInAir = 600;
protected double radiusModifier = 1;
protected double explosionModifier = 1;
protected double fillerChance = 0;
@Setter
public ItemStack meteorStack;
@ -28,7 +32,7 @@ public class EntityMeteor extends EntityThrowable implements IThrowableEntity
super(world);
}
public EntityMeteor(World world, double x, double y, double z, double velX, double velY, double velZ)
public EntityMeteor(World world, double x, double y, double z, double velX, double velY, double velZ, double radiusModifier, double explosionModifier, double fillerChance)
{
super(world);
this.setSize(1F, 1F);
@ -36,6 +40,9 @@ public class EntityMeteor extends EntityThrowable implements IThrowableEntity
motionX = velX;
motionY = velY;
motionZ = velZ;
this.radiusModifier = radiusModifier;
this.explosionModifier = explosionModifier;
this.fillerChance = fillerChance;
}
@Override
@ -88,7 +95,7 @@ public class EntityMeteor extends EntityThrowable implements IThrowableEntity
public void generateMeteor(BlockPos pos)
{
MeteorRegistry.generateMeteorForItem(meteorStack, worldObj, pos, Blocks.STONE.getDefaultState());
MeteorRegistry.generateMeteorForItem(meteorStack, worldObj, pos, Blocks.STONE.getDefaultState(), radiusModifier, explosionModifier, fillerChance);
}
public DamageSource getDamageSource()
@ -102,7 +109,9 @@ public class EntityMeteor extends EntityThrowable implements IThrowableEntity
super.writeEntityToNBT(nbt);
nbt.setInteger(Constants.NBT.PROJECTILE_TICKS_IN_AIR, ticksInAir);
nbt.setInteger(Constants.NBT.PROJECTILE_MAX_TICKS_IN_AIR, maxTicksInAir);
nbt.setDouble("radiusModifier", radiusModifier);
nbt.setDouble("explosionModifier", explosionModifier);
nbt.setDouble("fillerChance", fillerChance);
if (meteorStack != null)
{
meteorStack.writeToNBT(nbt);
@ -115,6 +124,9 @@ public class EntityMeteor extends EntityThrowable implements IThrowableEntity
super.readEntityFromNBT(nbt);
ticksInAir = nbt.getInteger(Constants.NBT.PROJECTILE_TICKS_IN_AIR);
maxTicksInAir = nbt.getInteger(Constants.NBT.PROJECTILE_MAX_TICKS_IN_AIR);
radiusModifier = nbt.getDouble("radiusModifier");
explosionModifier = nbt.getDouble("explosionModifier");
fillerChance = nbt.getDouble("fillerChance");
meteorStack = ItemStack.loadItemStackFromNBT(nbt);
}

View file

@ -4,12 +4,14 @@ import java.util.ArrayList;
import java.util.List;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.passive.EntityAnimal;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.init.SoundEvents;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.SoundCategory;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
@ -17,8 +19,9 @@ import WayofTime.bloodmagic.BloodMagic;
import WayofTime.bloodmagic.ConfigHandler;
import WayofTime.bloodmagic.api.BloodMagicAPI;
import WayofTime.bloodmagic.api.Constants;
import WayofTime.bloodmagic.client.IVariantProvider;
import WayofTime.bloodmagic.api.util.helper.PlayerSacrificeHelper;
import WayofTime.bloodmagic.api.util.helper.PurificationHelper;
import WayofTime.bloodmagic.client.IVariantProvider;
public class ItemDaggerOfSacrifice extends Item implements IVariantProvider
{
@ -47,17 +50,23 @@ public class ItemDaggerOfSacrifice extends Item implements IVariantProvider
return false;
String entityName = target.getClass().getSimpleName();
int lifeEssence = 500;
int lifeEssenceRatio = 25;
if (ConfigHandler.entitySacrificeValues.containsKey(entityName))
lifeEssence = ConfigHandler.entitySacrificeValues.get(entityName);
lifeEssenceRatio = ConfigHandler.entitySacrificeValues.get(entityName);
if (BloodMagicAPI.getEntitySacrificeValues().containsKey(entityName))
lifeEssence = BloodMagicAPI.getEntitySacrificeValues().get(entityName);
lifeEssenceRatio = BloodMagicAPI.getEntitySacrificeValues().get(entityName);
if (lifeEssence <= 0)
if (lifeEssenceRatio <= 0)
return false;
int lifeEssence = (int) (lifeEssenceRatio * target.getHealth());
if (target instanceof EntityAnimal)
{
lifeEssence = (int) (lifeEssence * (1 + PurificationHelper.getCurrentPurity((EntityAnimal) target)));
}
if (PlayerSacrificeHelper.findAndFillAltar(attacker.worldObj, target, lifeEssence, true))
{
target.worldObj.playSound(null, target.posX, target.posY, target.posZ, SoundEvents.BLOCK_FIRE_EXTINGUISH, SoundCategory.BLOCKS, 0.5F, 2.6F + (target.worldObj.rand.nextFloat() - target.worldObj.rand.nextFloat()) * 0.8F);

View file

@ -34,17 +34,19 @@ public class Meteor
this.maxWeight = maxWeight;
}
public void generateMeteor(World world, BlockPos pos, IBlockState fillerBlock)
public void generateMeteor(World world, BlockPos pos, IBlockState fillerBlock, double radiusModifier, double explosionModifier, double fillerChance)
{
world.newExplosion(null, pos.getX(), pos.getY(), pos.getZ(), explosionStrength, true, true);
world.newExplosion(null, pos.getX(), pos.getY(), pos.getZ(), (float) (explosionStrength * explosionModifier), true, true);
int radius = (int) Math.ceil(getRadius() * radiusModifier);
double floatingRadius = getRadius() * radiusModifier;
for (int i = -getRadius(); i <= getRadius(); i++)
for (int i = -radius; i <= radius; i++)
{
for (int j = -getRadius(); j <= getRadius(); j++)
for (int j = -radius; j <= radius; j++)
{
for (int k = -getRadius(); k <= getRadius(); k++)
for (int k = -radius; k <= radius; k++)
{
if (i * i + j * j + k * k > (getRadius() + 0.5) * (getRadius() + 0.5))
if (i * i + j * j + k * k > (floatingRadius + 0.5) * (floatingRadius + 0.5))
{
continue;
}
@ -54,15 +56,19 @@ public class Meteor
if (world.isAirBlock(newPos) || Utils.isBlockLiquid(state))
{
IBlockState placedState = getRandomOreFromComponents(fillerBlock);
world.setBlockState(newPos, placedState);
IBlockState placedState = getRandomOreFromComponents(fillerBlock, fillerChance);
if (placedState != null)
{
world.setBlockState(newPos, placedState);
}
}
}
}
}
}
public IBlockState getRandomOreFromComponents(IBlockState fillerBlock)
//fillerChance is the chance that the filler block will NOT be placed
public IBlockState getRandomOreFromComponents(IBlockState fillerBlock, double fillerChance)
{
int goal = RAND.nextInt(getMaxWeight());
@ -77,11 +83,11 @@ public class Meteor
return state;
} else
{
return fillerBlock;
return RAND.nextDouble() > fillerChance ? fillerBlock : null;
}
}
}
return fillerBlock;
return RAND.nextDouble() > fillerChance ? fillerBlock : null;
}
}

View file

@ -41,12 +41,12 @@ public class MeteorRegistry
return wrapper != null ? meteorMap.get(wrapper) : null;
}
public static void generateMeteorForItem(ItemStack stack, World world, BlockPos pos, IBlockState fillerBlock)
public static void generateMeteorForItem(ItemStack stack, World world, BlockPos pos, IBlockState fillerBlock, double radiusModifier, double explosionModifier, double fillerChance)
{
Meteor holder = getMeteorForItem(stack);
if (holder != null)
{
holder.generateMeteor(world, pos, fillerBlock);
holder.generateMeteor(world, pos, fillerBlock, radiusModifier, explosionModifier, fillerChance);
}
}
}

View file

@ -4,6 +4,7 @@ import java.util.ArrayList;
import java.util.List;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.passive.EntityAnimal;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
@ -13,12 +14,12 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import WayofTime.bloodmagic.ConfigHandler;
import WayofTime.bloodmagic.api.Constants;
import WayofTime.bloodmagic.api.saving.SoulNetwork;
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.util.helper.NetworkHelper;
import WayofTime.bloodmagic.tile.TileDemonCrystal;
@ -127,8 +128,14 @@ public class RitualForsakenSoul extends Ritual
if (!entity.isEntityAlive())
{
int uniqueness = calculateUniqueness(entity);
willBuffer += getWillForUniqueness(uniqueness) / HEALTH_THRESHOLD * entity.getMaxHealth();
crystalBuffer += entity.getMaxHealth() / HEALTH_THRESHOLD;
double modifier = 1;
if (entity instanceof EntityAnimal && !entity.isCollided)
{
modifier = 4;
}
willBuffer += modifier * getWillForUniqueness(uniqueness) / HEALTH_THRESHOLD * entity.getMaxHealth();
crystalBuffer += modifier * entity.getMaxHealth() / HEALTH_THRESHOLD;
totalEffects++;
if (totalEffects >= maxEffects)

View file

@ -13,12 +13,17 @@ 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.EnumDemonWillType;
import WayofTime.bloodmagic.api.util.helper.NetworkHelper;
import WayofTime.bloodmagic.demonAura.WorldDemonWillHandler;
import WayofTime.bloodmagic.entity.projectile.EntityMeteor;
import WayofTime.bloodmagic.meteor.MeteorRegistry;
public class RitualMeteor extends Ritual
{
public static final String ITEM_RANGE = "itemRange";
public static final double destructiveWillDrain = 50;
public RitualMeteor()
{
@ -31,24 +36,66 @@ public class RitualMeteor extends Ritual
public void performRitual(IMasterRitualStone masterRitualStone)
{
World world = masterRitualStone.getWorldObj();
SoulNetwork network = NetworkHelper.getSoulNetwork(masterRitualStone.getOwner());
int currentEssence = network.getCurrentEssence();
BlockPos pos = masterRitualStone.getBlockPos();
List<EnumDemonWillType> willConfig = masterRitualStone.getActiveWillConfig();
double corrosiveWill = this.getWillRespectingConfig(world, pos, EnumDemonWillType.CORROSIVE, willConfig);
double destructiveWill = this.getWillRespectingConfig(world, pos, EnumDemonWillType.DESTRUCTIVE, willConfig);
double rawWill = this.getWillRespectingConfig(world, pos, EnumDemonWillType.DEFAULT, willConfig);
double steadfastWill = this.getWillRespectingConfig(world, pos, EnumDemonWillType.STEADFAST, willConfig);
double vengefulWill = this.getWillRespectingConfig(world, pos, EnumDemonWillType.VENGEFUL, willConfig);
AreaDescriptor itemDetectionRange = getBlockRange(ITEM_RANGE);
List<EntityItem> itemList = world.getEntitiesWithinAABB(EntityItem.class, itemDetectionRange.getAABB(pos));
double radiusModifier = getRadiusModifier(rawWill);
double explosionModifier = getExplosionModifier(steadfastWill);
double fillerChance = getFillerChance(corrosiveWill);
boolean successful = false;
for (EntityItem entityItem : itemList)
{
ItemStack stack = entityItem.getEntityItem();
if (MeteorRegistry.hasMeteorForItem(stack))
{
EntityMeteor meteor = new EntityMeteor(world, pos.getX(), 260, pos.getZ(), 0, -0.1, 0);
EntityMeteor meteor = new EntityMeteor(world, pos.getX(), 260, pos.getZ(), 0, -0.1, 0, radiusModifier, explosionModifier, fillerChance);
meteor.setMeteorStack(stack.copy());
world.spawnEntityInWorld(meteor);
entityItem.setDead();
masterRitualStone.setActive(false);
if (destructiveWill >= destructiveWillDrain && currentEssence >= 1000000000)
{
network.syphon(1000000);
} else
{
masterRitualStone.setActive(false);
}
successful = true;
break;
}
}
if (successful)
{
if (rawWill > 0)
{
WorldDemonWillHandler.drainWill(world, pos, EnumDemonWillType.DEFAULT, rawWill, true);
}
if (corrosiveWill > 0)
{
WorldDemonWillHandler.drainWill(world, pos, EnumDemonWillType.CORROSIVE, corrosiveWill, true);
}
if (steadfastWill > 0)
{
WorldDemonWillHandler.drainWill(world, pos, EnumDemonWillType.STEADFAST, steadfastWill, true);
}
}
}
@ -105,4 +152,19 @@ public class RitualMeteor extends Ritual
{
return new RitualMeteor();
}
public double getRadiusModifier(double rawWill)
{
return Math.pow(1 + rawWill / 100, 1 / 3);
}
public double getFillerChance(double corrosiveWill)
{
return corrosiveWill / 200;
}
public double getExplosionModifier(double steadfastWill)
{
return Math.max(Math.pow(0.4, steadfastWill / 100), 1);
}
}

View file

@ -23,7 +23,7 @@ public class RitualWellOfSuffering extends Ritual
public static final String ALTAR_RANGE = "altar";
public static final String DAMAGE_RANGE = "damage";
public static final int SACRIFICE_AMOUNT = 20;
public static final int SACRIFICE_AMOUNT = 25;
public BlockPos altarOffsetPos = new BlockPos(0, 0, 0); //TODO: Save!
@ -99,7 +99,17 @@ public class RitualWellOfSuffering extends Ritual
{
if (entity.attackEntityFrom(DamageSource.outOfWorld, 1))
{
tileAltar.sacrificialDaggerCall(SACRIFICE_AMOUNT, true);
String entityName = entity.getClass().getSimpleName();
int lifeEssenceRatio = SACRIFICE_AMOUNT;
if (ConfigHandler.entitySacrificeValues.containsKey(entityName))
lifeEssenceRatio = ConfigHandler.entitySacrificeValues.get(entityName);
if (BloodMagicAPI.getEntitySacrificeValues().containsKey(entityName))
lifeEssenceRatio = BloodMagicAPI.getEntitySacrificeValues().get(entityName);
tileAltar.sacrificialDaggerCall(lifeEssenceRatio, true);
totalEffects++;

View file

@ -0,0 +1,96 @@
package WayofTime.bloodmagic.tile;
import java.util.List;
import net.minecraft.entity.passive.EntityAnimal;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.ITickable;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.WorldServer;
import WayofTime.bloodmagic.api.iface.IPurificationAsh;
import WayofTime.bloodmagic.api.ritual.AreaDescriptor;
import WayofTime.bloodmagic.api.util.helper.PurificationHelper;
public class TilePurificationAltar extends TileInventory implements ITickable
{
public AreaDescriptor purityArea = new AreaDescriptor.Rectangle(new BlockPos(-5, -5, -5), 11);
public double totalPurity = 0;
public double maxPurity = 0;
public double purityRate = 0;
public TilePurificationAltar()
{
super(1, "purificationAltar");
}
@Override
public void update()
{
if (totalPurity <= 0)
{
ItemStack stack = this.getStackInSlot(0);
if (stack != null && stack.getItem() instanceof IPurificationAsh)
{
totalPurity = ((IPurificationAsh) stack.getItem()).getTotalPurity(stack);
maxPurity = ((IPurificationAsh) stack.getItem()).getMaxPurity(stack);
purityRate = ((IPurificationAsh) stack.getItem()).getPurityRate(stack);
}
} else
{
return;
}
AxisAlignedBB aabb = purityArea.getAABB(getPos());
List<EntityAnimal> animalList = worldObj.getEntitiesWithinAABB(EntityAnimal.class, aabb);
if (animalList.isEmpty())
{
return;
}
boolean hasPerformed = false;
for (EntityAnimal animal : animalList)
{
double added = PurificationHelper.addPurity(animal, Math.min(purityRate, totalPurity), maxPurity);
if (added > 0)
{
totalPurity -= purityRate;
hasPerformed = true;
}
}
if (hasPerformed)
{
if (worldObj.rand.nextInt(4) == 0 && worldObj instanceof WorldServer)
{
WorldServer server = (WorldServer) worldObj;
server.spawnParticle(EnumParticleTypes.FLAME, pos.getX() + 0.5, pos.getY() + 1.2, pos.getZ() + 0.5, 1, 0.02, 0.03, 0.02, 0, new int[0]);
}
}
}
@Override
public void deserialize(NBTTagCompound tag)
{
super.deserialize(tag);
totalPurity = tag.getDouble("totalPurity");
maxPurity = tag.getDouble("maxPurity");
purityRate = tag.getDouble("purityRate");
}
@Override
public NBTTagCompound serialize(NBTTagCompound tag)
{
super.serialize(tag);
tag.setDouble("totalPurity", totalPurity);
tag.setDouble("maxPurity", maxPurity);
tag.setDouble("purityRate", purityRate);
return tag;
}
}