Did a lot of work on the behaviour of the Inversion Pillar. Also added a Corrupted Zombie for later testing.

This commit is contained in:
WayofTime 2016-09-13 17:20:35 -04:00
parent d1455920ec
commit e9549fd9db
10 changed files with 529 additions and 9 deletions

View file

@ -0,0 +1,15 @@
package WayofTime.bloodmagic.client.render.entity;
import net.minecraft.client.renderer.entity.Render;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraftforge.fml.client.registry.IRenderFactory;
import WayofTime.bloodmagic.entity.mob.EntityCorruptedZombie;
public class CorruptedZombieRenderFactory implements IRenderFactory<EntityCorruptedZombie>
{
@Override
public Render<? super EntityCorruptedZombie> createRenderFor(RenderManager manager)
{
return new RenderCorruptedZombie(manager);
}
}

View file

@ -0,0 +1,102 @@
package WayofTime.bloodmagic.client.render.entity;
import java.util.List;
import net.minecraft.client.model.ModelBiped;
import net.minecraft.client.model.ModelZombie;
import net.minecraft.client.model.ModelZombieVillager;
import net.minecraft.client.renderer.entity.RenderBiped;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.client.renderer.entity.layers.LayerBipedArmor;
import net.minecraft.client.renderer.entity.layers.LayerCustomHead;
import net.minecraft.client.renderer.entity.layers.LayerHeldItem;
import net.minecraft.client.renderer.entity.layers.LayerRenderer;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import WayofTime.bloodmagic.entity.mob.EntityCorruptedZombie;
import com.google.common.collect.Lists;
@SideOnly(Side.CLIENT)
public class RenderCorruptedZombie extends RenderBiped<EntityCorruptedZombie>
{
private static final ResourceLocation ZOMBIE_TEXTURES = new ResourceLocation("bloodmagic", "textures/entities/zombie_raw.png");
private final ModelBiped defaultModel;
private final ModelZombieVillager zombieVillagerModel;
private final List<LayerRenderer<EntityCorruptedZombie>> defaultLayers;
public RenderCorruptedZombie(RenderManager renderManagerIn)
{
super(renderManagerIn, new ModelZombie(), 0.5F, 1.0F);
LayerRenderer<?> layerrenderer = (LayerRenderer) this.layerRenderers.get(0);
this.defaultModel = this.modelBipedMain;
this.zombieVillagerModel = new ModelZombieVillager();
this.addLayer(new LayerHeldItem(this));
LayerBipedArmor layerbipedarmor = new LayerBipedArmor(this)
{
protected void initArmor()
{
this.modelLeggings = new ModelZombie(0.5F, true);
this.modelArmor = new ModelZombie(1.0F, true);
}
};
this.addLayer(layerbipedarmor);
this.defaultLayers = Lists.newArrayList(this.layerRenderers);
if (layerrenderer instanceof LayerCustomHead)
{
this.removeLayer(layerrenderer);
this.addLayer(new LayerCustomHead(this.zombieVillagerModel.bipedHead));
}
this.removeLayer(layerbipedarmor);
}
/**
* Allows the render to do state modifications necessary before the model is
* rendered.
*/
protected void preRenderCallback(EntityCorruptedZombie entitylivingbaseIn, float partialTickTime)
{
super.preRenderCallback(entitylivingbaseIn, partialTickTime);
}
/**
* Renders the desired {@code T} type Entity.
*/
public void doRender(EntityCorruptedZombie entity, double x, double y, double z, float entityYaw, float partialTicks)
{
this.swapArmor(entity);
super.doRender(entity, x, y, z, entityYaw, partialTicks);
}
/**
* Returns the location of an entity's texture. Doesn't seem to be called
* unless you call Render.bindEntityTexture.
*/
protected ResourceLocation getEntityTexture(EntityCorruptedZombie entity)
{
{
return ZOMBIE_TEXTURES;
}
}
private void swapArmor(EntityCorruptedZombie zombie)
{
{
this.mainModel = this.defaultModel;
this.layerRenderers = this.defaultLayers;
}
this.modelBipedMain = (ModelBiped) this.mainModel;
}
protected void rotateCorpse(EntityCorruptedZombie entityLiving, float p_77043_2_, float p_77043_3_, float partialTicks)
{
super.rotateCorpse(entityLiving, p_77043_2_, p_77043_3_, partialTicks);
}
}

View file

@ -0,0 +1,227 @@
package WayofTime.bloodmagic.entity.mob;
import lombok.Getter;
import lombok.Setter;
import net.minecraft.block.Block;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.EntityAIAttackMelee;
import net.minecraft.entity.monster.EntityCreeper;
import net.minecraft.entity.monster.EntityGhast;
import net.minecraft.init.SoundEvents;
import net.minecraft.item.ItemBow;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.DamageSource;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.EnumDifficulty;
import net.minecraft.world.World;
import WayofTime.bloodmagic.api.Constants;
import WayofTime.bloodmagic.api.soul.EnumDemonWillType;
import WayofTime.bloodmagic.demonAura.WorldDemonWillHandler;
import WayofTime.bloodmagic.entity.ai.EntityAIAttackRangedBow;
public class EntityCorruptedZombie extends EntityDemonBase
{
@Getter
@Setter
protected EnumDemonWillType type = EnumDemonWillType.DEFAULT;
private final EntityAIAttackRangedBow aiArrowAttack = new EntityAIAttackRangedBow(this, 1.0D, 20, 15.0F);
private final EntityAIAttackMelee aiAttackOnCollide = new EntityAIAttackMelee(this, 1.0D, false);
private final int attackPriority = 3;
public EntityCorruptedZombie(World worldIn)
{
super(worldIn);
this.setSize(0.6F, 1.95F);
// ((PathNavigateGround) getNavigator()).setCanSwim(false);
this.setCombatTask();
// this.targetTasks.addTask(8, new EntityAINearestAttackableTarget<EntityMob>(this, EntityMob.class, 10, true, false, new TargetPredicate(this)));
}
@Override
protected void applyEntityAttributes()
{
super.applyEntityAttributes();
getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(40.0D);
getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).setBaseValue(6.0D);
getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0.27D);
}
@Override
public void setCombatTask()
{
if (this.worldObj != null && !this.worldObj.isRemote)
{
this.tasks.removeTask(this.aiAttackOnCollide);
this.tasks.removeTask(this.aiArrowAttack);
ItemStack itemstack = this.getHeldItemMainhand();
if (itemstack != null && itemstack.getItem() instanceof ItemBow)
{
int i = 20;
if (this.worldObj.getDifficulty() != EnumDifficulty.HARD)
{
i = 40;
}
this.aiArrowAttack.setAttackCooldown(i);
this.tasks.addTask(attackPriority, this.aiArrowAttack);
} else
{
this.tasks.addTask(attackPriority, this.aiAttackOnCollide);
}
}
}
@Override
public boolean attackEntityFrom(DamageSource source, float amount)
{
return this.isEntityInvulnerable(source) ? false : super.attackEntityFrom(source, amount);
}
/**
* Redone from EntityMob to prevent despawning on peaceful.
*/
@Override
public boolean attackEntityAsMob(Entity attackedEntity)
{
boolean flag = super.attackEntityAsMob(attackedEntity);
if (flag)
{
//EMPTY
return true;
} else
{
return false;
}
}
/**
* @param toHeal
* @return Amount of Will consumed from the Aura to heal
*/
public double absorbWillFromAuraToHeal(double toHeal)
{
if (worldObj.isRemote)
{
return 0;
}
double healthMissing = this.getMaxHealth() - this.getHealth();
if (healthMissing <= 0)
{
return 0;
}
double will = WorldDemonWillHandler.getCurrentWill(worldObj, getPosition(), getType());
toHeal = Math.min(healthMissing, Math.min(toHeal, will / getWillToHealth()));
if (toHeal > 0)
{
this.heal((float) toHeal);
return WorldDemonWillHandler.drainWill(worldObj, getPosition(), getType(), toHeal * getWillToHealth(), true);
}
return 0;
}
public double getWillToHealth()
{
return 2;
}
@Override
protected boolean canDespawn()
{
return !this.isTamed() && super.canDespawn();
}
public void onUpdate()
{
if (!this.worldObj.isRemote && this.ticksExisted % 20 == 0)
{
absorbWillFromAuraToHeal(2);
}
super.onUpdate();
}
@Override
public void writeEntityToNBT(NBTTagCompound tag)
{
super.writeEntityToNBT(tag);
tag.setString(Constants.NBT.WILL_TYPE, type.toString());
}
@Override
public void readEntityFromNBT(NBTTagCompound tag)
{
super.readEntityFromNBT(tag);
if (!tag.hasKey(Constants.NBT.WILL_TYPE))
{
type = EnumDemonWillType.DEFAULT;
} else
{
type = EnumDemonWillType.valueOf(tag.getString(Constants.NBT.WILL_TYPE));
}
this.setCombatTask();
}
//TODO: Change to fit the given AI
@Override
public boolean shouldAttackEntity(EntityLivingBase attacker, EntityLivingBase owner)
{
if (!(attacker instanceof EntityCreeper) && !(attacker instanceof EntityGhast))
{
return super.shouldAttackEntity(attacker, owner);
} else
{
return false;
}
}
@Override
protected SoundEvent getAmbientSound()
{
return SoundEvents.ENTITY_COW_AMBIENT;
}
@Override
protected SoundEvent getHurtSound()
{
return SoundEvents.ENTITY_COW_HURT;
}
@Override
protected SoundEvent getDeathSound()
{
return SoundEvents.ENTITY_COW_DEATH;
}
@Override
protected void playStepSound(BlockPos pos, Block block)
{
this.playSound(SoundEvents.ENTITY_COW_STEP, 0.15F, 1.0F);
}
/**
* Returns the volume for the sounds this mob makes.
*/
@Override
protected float getSoundVolume()
{
return 0.4F;
}
}

View file

@ -198,4 +198,52 @@ public class InversionPillarHandler
return new ArrayList<BlockPos>(); return new ArrayList<BlockPos>();
} }
public static List<BlockPos> getAllConnectedPillars(World world, EnumDemonWillType type, BlockPos pos)
{
List<BlockPos> checkedPosList = new ArrayList<BlockPos>();
List<BlockPos> uncheckedPosList = new ArrayList<BlockPos>(); //Positions where we did not check their connections.
uncheckedPosList.add(pos);
int dim = world.provider.getDimension();
if (nearPillarMap.containsKey(dim))
{
Map<EnumDemonWillType, Map<BlockPos, List<BlockPos>>> willMap = nearPillarMap.get(dim);
if (willMap.containsKey(type))
{
Map<BlockPos, List<BlockPos>> posMap = willMap.get(type);
// This is where the magic happens.
while (!uncheckedPosList.isEmpty())
{
//Positions that are new this iteration and need to be dumped into uncheckedPosList next iteration.
List<BlockPos> newPosList = new ArrayList<BlockPos>();
Iterator<BlockPos> itr = uncheckedPosList.iterator();
while (itr.hasNext())
{
BlockPos checkPos = itr.next();
List<BlockPos> posList = posMap.get(checkPos);
if (posList != null)
{
for (BlockPos testPos : posList)
{
//Check if the position has already been checked, is scheduled to be checked, or is already found it needs to be checked.
if (!checkedPosList.contains(testPos) && !uncheckedPosList.contains(testPos) && !newPosList.contains(testPos))
{
newPosList.add(testPos);
}
}
}
}
checkedPosList.addAll(uncheckedPosList);
uncheckedPosList = newPosList;
}
}
}
return checkedPosList;
}
} }

View file

@ -12,13 +12,12 @@ import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.util.text.TextComponentTranslation;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import WayofTime.bloodmagic.api.altar.IBloodAltar; import WayofTime.bloodmagic.api.altar.IBloodAltar;
import WayofTime.bloodmagic.api.iface.IAltarReader; import WayofTime.bloodmagic.api.iface.IAltarReader;
import WayofTime.bloodmagic.api.util.helper.NetworkHelper; import WayofTime.bloodmagic.api.util.helper.NetworkHelper;
import WayofTime.bloodmagic.api.util.helper.PlayerHelper; import WayofTime.bloodmagic.api.util.helper.PlayerHelper;
import WayofTime.bloodmagic.structures.DungeonTester;
import WayofTime.bloodmagic.tile.TileIncenseAltar; import WayofTime.bloodmagic.tile.TileIncenseAltar;
import WayofTime.bloodmagic.tile.TileInversionPillar;
import WayofTime.bloodmagic.util.ChatUtil; import WayofTime.bloodmagic.util.ChatUtil;
import WayofTime.bloodmagic.util.helper.NumeralHelper; import WayofTime.bloodmagic.util.helper.NumeralHelper;
@ -38,6 +37,13 @@ public class ItemSigilDivination extends ItemSigilBase implements IAltarReader
//// BuildTestStructure s = new BuildTestStructure(); //// BuildTestStructure s = new BuildTestStructure();
//// s.placeStructureAtPosition(new Random(), Rotation.CLOCKWISE_180, (WorldServer) world, player.getPosition(), 0); //// s.placeStructureAtPosition(new Random(), Rotation.CLOCKWISE_180, (WorldServer) world, player.getPosition(), 0);
// DungeonTester.testDungeonElementWithOutput((WorldServer) world, player.getPosition()); // DungeonTester.testDungeonElementWithOutput((WorldServer) world, player.getPosition());
// }
// if (!world.isRemote)
// {
// EntityCorruptedZombie fred = new EntityCorruptedZombie(world);
// fred.setPosition(player.posX, player.posY, player.posZ);
// world.spawnEntityInWorld(fred);
// } // }
if (!world.isRemote) if (!world.isRemote)
@ -74,7 +80,13 @@ public class ItemSigilDivination extends ItemSigilBase implements IAltarReader
altar.recheckConstruction(); altar.recheckConstruction();
double tranquility = altar.tranquility; double tranquility = altar.tranquility;
ChatUtil.sendNoSpam(player, new TextComponentTranslation(tooltipBase + "currentTranquility", (int) ((100D * (int) (100 * tranquility)) / 100d)), new TextComponentTranslation(tooltipBase + "currentBonus", (int) (100 * altar.incenseAddition))); ChatUtil.sendNoSpam(player, new TextComponentTranslation(tooltipBase + "currentTranquility", (int) ((100D * (int) (100 * tranquility)) / 100d)), new TextComponentTranslation(tooltipBase + "currentBonus", (int) (100 * altar.incenseAddition)));
} else if (tile != null && tile instanceof TileInversionPillar)
{
TileInversionPillar pillar = (TileInversionPillar) tile;
double inversion = pillar.getCurrentInversion();
ChatUtil.sendNoSpam(player, new TextComponentTranslation(tooltipBase + "currentInversion", ((int) (10 * inversion)) / 10d));
} else } else
{ {
int currentEssence = NetworkHelper.getSoulNetwork(getOwnerUUID(stack)).getCurrentEssence(); int currentEssence = NetworkHelper.getSoulNetwork(getOwnerUUID(stack)).getCurrentEssence();
ChatUtil.sendNoSpam(player, new TextComponentTranslation(tooltipBase + "currentEssence", currentEssence)); ChatUtil.sendNoSpam(player, new TextComponentTranslation(tooltipBase + "currentEssence", currentEssence));

View file

@ -35,11 +35,13 @@ import WayofTime.bloodmagic.client.render.RenderDemonCrucible;
import WayofTime.bloodmagic.client.render.RenderItemRoutingNode; import WayofTime.bloodmagic.client.render.RenderItemRoutingNode;
import WayofTime.bloodmagic.client.render.block.RenderMimic; import WayofTime.bloodmagic.client.render.block.RenderMimic;
import WayofTime.bloodmagic.client.render.entity.BloodLightRenderFactory; import WayofTime.bloodmagic.client.render.entity.BloodLightRenderFactory;
import WayofTime.bloodmagic.client.render.entity.CorruptedZombieRenderFactory;
import WayofTime.bloodmagic.client.render.entity.MeteorRenderFactory; import WayofTime.bloodmagic.client.render.entity.MeteorRenderFactory;
import WayofTime.bloodmagic.client.render.entity.MimicRenderFactory; import WayofTime.bloodmagic.client.render.entity.MimicRenderFactory;
import WayofTime.bloodmagic.client.render.entity.SentientArrowRenderFactory; import WayofTime.bloodmagic.client.render.entity.SentientArrowRenderFactory;
import WayofTime.bloodmagic.client.render.entity.SentientSpecterRenderFactory; import WayofTime.bloodmagic.client.render.entity.SentientSpecterRenderFactory;
import WayofTime.bloodmagic.client.render.entity.SoulSnareRenderFactory; import WayofTime.bloodmagic.client.render.entity.SoulSnareRenderFactory;
import WayofTime.bloodmagic.entity.mob.EntityCorruptedZombie;
import WayofTime.bloodmagic.entity.mob.EntityMimic; import WayofTime.bloodmagic.entity.mob.EntityMimic;
import WayofTime.bloodmagic.entity.mob.EntitySentientSpecter; import WayofTime.bloodmagic.entity.mob.EntitySentientSpecter;
import WayofTime.bloodmagic.entity.projectile.EntityBloodLight; import WayofTime.bloodmagic.entity.projectile.EntityBloodLight;
@ -104,6 +106,7 @@ public class ClientProxy extends CommonProxy
RenderingRegistry.registerEntityRenderingHandler(EntityMeteor.class, new MeteorRenderFactory()); RenderingRegistry.registerEntityRenderingHandler(EntityMeteor.class, new MeteorRenderFactory());
RenderingRegistry.registerEntityRenderingHandler(EntitySentientSpecter.class, new SentientSpecterRenderFactory()); RenderingRegistry.registerEntityRenderingHandler(EntitySentientSpecter.class, new SentientSpecterRenderFactory());
RenderingRegistry.registerEntityRenderingHandler(EntityMimic.class, new MimicRenderFactory()); RenderingRegistry.registerEntityRenderingHandler(EntityMimic.class, new MimicRenderFactory());
RenderingRegistry.registerEntityRenderingHandler(EntityCorruptedZombie.class, new CorruptedZombieRenderFactory());
ShaderHelper.init(); ShaderHelper.init();
} }

View file

@ -2,6 +2,7 @@ package WayofTime.bloodmagic.registry;
import net.minecraftforge.fml.common.registry.EntityRegistry; import net.minecraftforge.fml.common.registry.EntityRegistry;
import WayofTime.bloodmagic.BloodMagic; import WayofTime.bloodmagic.BloodMagic;
import WayofTime.bloodmagic.entity.mob.EntityCorruptedZombie;
import WayofTime.bloodmagic.entity.mob.EntityMimic; import WayofTime.bloodmagic.entity.mob.EntityMimic;
import WayofTime.bloodmagic.entity.mob.EntitySentientSpecter; import WayofTime.bloodmagic.entity.mob.EntitySentientSpecter;
import WayofTime.bloodmagic.entity.projectile.EntityBloodLight; import WayofTime.bloodmagic.entity.projectile.EntityBloodLight;
@ -21,5 +22,6 @@ public class ModEntities
EntityRegistry.registerModEntity(EntityMeteor.class, "Meteor", id++, BloodMagic.instance, 64, 1, true); EntityRegistry.registerModEntity(EntityMeteor.class, "Meteor", id++, BloodMagic.instance, 64, 1, true);
EntityRegistry.registerModEntity(EntitySentientSpecter.class, "SentientSpecter", id++, BloodMagic.instance, 64, 1, true); EntityRegistry.registerModEntity(EntitySentientSpecter.class, "SentientSpecter", id++, BloodMagic.instance, 64, 1, true);
EntityRegistry.registerModEntity(EntityMimic.class, "Mimic", id++, BloodMagic.instance, 64, 1, true); EntityRegistry.registerModEntity(EntityMimic.class, "Mimic", id++, BloodMagic.instance, 64, 1, true);
EntityRegistry.registerModEntity(EntityCorruptedZombie.class, "CorruptedZombie", id++, BloodMagic.instance, 64, 1, true);
} }
} }

View file

@ -1,5 +1,6 @@
package WayofTime.bloodmagic.tile; package WayofTime.bloodmagic.tile;
import java.util.Collections;
import java.util.List; import java.util.List;
import lombok.Getter; import lombok.Getter;
@ -8,7 +9,10 @@ import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks; import net.minecraft.init.Blocks;
import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import WayofTime.bloodmagic.api.Constants; import WayofTime.bloodmagic.api.Constants;
import WayofTime.bloodmagic.api.soul.EnumDemonWillType; import WayofTime.bloodmagic.api.soul.EnumDemonWillType;
import WayofTime.bloodmagic.demonAura.WorldDemonWillHandler; import WayofTime.bloodmagic.demonAura.WorldDemonWillHandler;
@ -25,10 +29,15 @@ public class TileInversionPillar extends TileTicking
public static double inversionToIncreaseRadius = 100; public static double inversionToIncreaseRadius = 100;
public static double inversionToAddPillar = 200; public static double inversionToAddPillar = 200;
public static double operationThreshold = 20; public static double operationThreshold = 20;
public static double inversionToSpreadWill = 200;
public static double willPushRate = 3;
public static double inversionCostPerWillSpread = 4;
public static double minimumWillForChunkWhenSpreading = 100;
public EnumDemonWillType type; public EnumDemonWillType type;
public double currentInversion = 0; public double currentInversion = 0;
public int consecutiveFailedChecks = 0; //If you fail enough checks, increase the radius. public int consecutiveFailedChecks = 0; //If you fail enough checks, increase the radius.
public int consecutiveFailedAirChecks = 0;
public int currentInfectionRadius = 1; public int currentInfectionRadius = 1;
public int counter = 0; public int counter = 0;
@ -76,9 +85,19 @@ public class TileInversionPillar extends TileTicking
if (pollute == 1) if (pollute == 1)
{ {
consecutiveFailedChecks++; consecutiveFailedChecks++;
} else if (pollute == 3)
{
consecutiveFailedAirChecks++;
} else if (pollute == 0) } else if (pollute == 0)
{ {
//We successfully found a block to replace!
consecutiveFailedChecks = 0; consecutiveFailedChecks = 0;
consecutiveFailedAirChecks = 0;
}
if (currentInversion >= inversionToSpreadWill)
{
spreadWillToSurroundingChunks();
} }
if (consecutiveFailedChecks > 5 * currentInfectionRadius && currentInversion >= inversionToIncreaseRadius) if (consecutiveFailedChecks > 5 * currentInfectionRadius && currentInversion >= inversionToIncreaseRadius)
@ -91,7 +110,97 @@ public class TileInversionPillar extends TileTicking
if (currentInfectionRadius >= 10 && currentInversion >= inversionToAddPillar) if (currentInfectionRadius >= 10 && currentInversion >= inversionToAddPillar)
{ {
//TODO: Spawn pillar //TODO: Improve algorithm
List<BlockPos> allConnectedPos = InversionPillarHandler.getAllConnectedPillars(worldObj, type, pos);
BlockPos candidatePos = findCandidatePositionForPillar(worldObj, type, pos, allConnectedPos, 5, 10);
if (!candidatePos.equals(BlockPos.ORIGIN))
{
currentInversion -= inversionToAddPillar;
IBlockState pillarState = ModBlocks.INVERSION_PILLAR.getStateFromMeta(type.ordinal());
IBlockState bottomState = ModBlocks.INVERSION_PILLAR_END.getStateFromMeta(type.ordinal() * 2);
IBlockState topState = ModBlocks.INVERSION_PILLAR_END.getStateFromMeta(type.ordinal() * 2 + 1);
worldObj.setBlockState(candidatePos, pillarState);
worldObj.setBlockState(candidatePos.down(), bottomState);
worldObj.setBlockState(candidatePos.up(), topState);
}
}
}
}
public static BlockPos findCandidatePositionForPillar(World world, EnumDemonWillType type, BlockPos pos, List<BlockPos> posList, double tooCloseDistance, double wantedAverageDistance)
{
int maxIterations = 100;
int heightCheckRange = 3;
for (int i = 0; i < maxIterations; i++)
{
Collections.shuffle(posList);
BlockPos pillarPos = posList.get(0);
Vec3d vec = new Vec3d(world.rand.nextDouble() * 2 - 1, world.rand.nextDouble() * 2 - 1, world.rand.nextDouble() * 2 - 1).normalize().scale(wantedAverageDistance);
BlockPos centralPos = pillarPos.add(vec.xCoord, vec.yCoord, vec.zCoord);
BlockPos testPos = null;
candidateTest: for (int h = 0; h <= heightCheckRange; h++)
{
for (int sig = -1; sig <= 1; sig += (h > 0 ? 2 : 3))
{
BlockPos candidatePos = centralPos.add(0, sig * h, 0);
IBlockState candidateState = world.getBlockState(candidatePos);
if (world.isAirBlock(candidatePos) && world.isAirBlock(candidatePos.up()) && world.isAirBlock(candidatePos.down()) && !world.isAirBlock(candidatePos.down(2)))
{
testPos = candidatePos;
break candidateTest;
}
}
}
if (testPos != null)
{
boolean isValid = true;
for (BlockPos pillarTestPos : posList)
{
if (pillarTestPos.distanceSq(testPos) <= tooCloseDistance * tooCloseDistance)
{
isValid = false;
break;
}
}
if (isValid)
{
return testPos;
}
}
}
return BlockPos.ORIGIN;
}
public void spreadWillToSurroundingChunks()
{
double currentAmount = WorldDemonWillHandler.getCurrentWill(worldObj, pos, type);
if (currentAmount <= minimumWillForChunkWhenSpreading)
{
return;
}
for (EnumFacing side : EnumFacing.HORIZONTALS)
{
BlockPos offsetPos = pos.offset(side, 16);
double sideAmount = WorldDemonWillHandler.getCurrentWill(worldObj, offsetPos, type);
if (currentAmount > sideAmount)
{
double drainAmount = Math.min((currentAmount - sideAmount) / 2, willPushRate);
if (drainAmount < willPushRate / 2)
{
continue;
}
double drain = WorldDemonWillHandler.drainWill(worldObj, pos, type, drainAmount, true);
drain = WorldDemonWillHandler.fillWillToMaximum(worldObj, offsetPos, type, drain, maxWillForChunk, true);
currentInversion -= drain * inversionCostPerWillSpread;
} }
} }
} }
@ -176,14 +285,15 @@ public class TileInversionPillar extends TileTicking
* @param currentWillInChunk * @param currentWillInChunk
* @return 0 if the block is successfully placed, 1 if the block is not * @return 0 if the block is successfully placed, 1 if the block is not
* placed due to the selected place being invalid, 2 if the block is * placed due to the selected place being invalid, 2 if the block is
* not placed due to there not being enough Will or Inversion * not placed due to there not being enough Will or Inversion, 3 if
* the block is not placed due to the selected block being air.
*/ */
public int polluteNearbyBlocks(double currentWillInChunk) public int polluteNearbyBlocks(double currentWillInChunk)
{ {
// System.out.println("Hai! :D Current Inversion: " + currentInversion + ", Current Will: " + currentWillInChunk); // System.out.println("Hai! :D Current Inversion: " + currentInversion + ", Current Will: " + currentWillInChunk);
if (currentWillInChunk < operationThreshold || currentInversion < inversionPerOperation) if (currentWillInChunk < operationThreshold || currentInversion < inversionPerOperation)
{ {
return 2; return 2; //Not enough Will or Inversion available
} }
double xOff = worldObj.rand.nextGaussian() * currentInfectionRadius; double xOff = worldObj.rand.nextGaussian() * currentInfectionRadius;
@ -202,7 +312,7 @@ public class TileInversionPillar extends TileTicking
BlockPos offsetPos = pos.add(xOff + 0.5, yOff + 0.5, zOff + 0.5); BlockPos offsetPos = pos.add(xOff + 0.5, yOff + 0.5, zOff + 0.5);
if (offsetPos.equals(pos)) if (offsetPos.equals(pos))
{ {
return 1; return 1; //Invalid block (itself!)
} }
IBlockState state = worldObj.getBlockState(offsetPos); IBlockState state = worldObj.getBlockState(offsetPos);
@ -218,13 +328,13 @@ public class TileInversionPillar extends TileTicking
WorldDemonWillHandler.drainWill(worldObj, pos, type, willPerOperation, true); WorldDemonWillHandler.drainWill(worldObj, pos, type, willPerOperation, true);
currentInversion -= inversionPerOperation; currentInversion -= inversionPerOperation;
return 0; return 0; //Successfully placed
} }
} }
return 1; return 1; //Invalid block
} }
return 1; return 3; //The block was air
} }
} }

View file

@ -383,6 +383,7 @@ tooltip.BloodMagic.sigil.divination.currentAltarTier=Current Tier: %d
tooltip.BloodMagic.sigil.divination.currentEssence=Current Essence: %d LP tooltip.BloodMagic.sigil.divination.currentEssence=Current Essence: %d LP
tooltip.BloodMagic.sigil.divination.currentAltarCapacity=Current Capacity: %d LP tooltip.BloodMagic.sigil.divination.currentAltarCapacity=Current Capacity: %d LP
tooltip.BloodMagic.sigil.divination.currentTranquility=Current Tranquility: %d tooltip.BloodMagic.sigil.divination.currentTranquility=Current Tranquility: %d
tooltip.BloodMagic.sigil.divination.currentInversion=Current Inversion: %d
tooltip.BloodMagic.sigil.divination.currentBonus=Current Bonus: +%d%% tooltip.BloodMagic.sigil.divination.currentBonus=Current Bonus: +%d%%
tooltip.BloodMagic.sigil.water.desc=&oInfinite water, anyone? tooltip.BloodMagic.sigil.water.desc=&oInfinite water, anyone?
tooltip.BloodMagic.sigil.lava.desc=&oHOT! DO NOT EAT tooltip.BloodMagic.sigil.lava.desc=&oHOT! DO NOT EAT

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB