diff --git a/src/main/java/WayofTime/bloodmagic/BloodMagic.java b/src/main/java/WayofTime/bloodmagic/BloodMagic.java index 3b3cea4d..25a2e5d8 100644 --- a/src/main/java/WayofTime/bloodmagic/BloodMagic.java +++ b/src/main/java/WayofTime/bloodmagic/BloodMagic.java @@ -31,6 +31,7 @@ import WayofTime.bloodmagic.proxy.CommonProxy; import WayofTime.bloodmagic.registry.ModArmourTrackers; import WayofTime.bloodmagic.registry.ModBlocks; import WayofTime.bloodmagic.registry.ModCompatibility; +import WayofTime.bloodmagic.registry.ModCorruptionBlocks; import WayofTime.bloodmagic.registry.ModEntities; import WayofTime.bloodmagic.registry.ModItems; import WayofTime.bloodmagic.registry.ModPotions; @@ -131,6 +132,7 @@ public class BloodMagic ModArmourTrackers.init(); ModCompatibility.loadCompat(ICompatibility.InitializationPhase.INIT); NetworkRegistry.INSTANCE.registerGuiHandler(BloodMagic.instance, new GuiHandler()); + ModCorruptionBlocks.init(); proxy.init(); } diff --git a/src/main/java/WayofTime/bloodmagic/client/render/entity/RenderCorruptedSheep.java b/src/main/java/WayofTime/bloodmagic/client/render/entity/RenderCorruptedSheep.java index 0dcf9c92..111d222b 100644 --- a/src/main/java/WayofTime/bloodmagic/client/render/entity/RenderCorruptedSheep.java +++ b/src/main/java/WayofTime/bloodmagic/client/render/entity/RenderCorruptedSheep.java @@ -5,6 +5,7 @@ import net.minecraft.client.renderer.entity.RenderManager; import net.minecraft.util.ResourceLocation; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import WayofTime.bloodmagic.client.render.entity.layer.LayerAlchemyCircle; import WayofTime.bloodmagic.client.render.entity.layer.LayerCorruptedSheepWool; import WayofTime.bloodmagic.client.render.entity.layer.LayerWill; import WayofTime.bloodmagic.client.render.model.ModelCorruptedSheep; @@ -22,6 +23,7 @@ public class RenderCorruptedSheep extends RenderLiving this.addLayer(new LayerCorruptedSheepWool(this)); this.addLayer(new LayerWill(this, new ModelCorruptedSheep(1.1f))); this.addLayer(new LayerWill(this, new ModelCorruptedSheep2(1.1f))); + this.addLayer(new LayerAlchemyCircle()); } @Override diff --git a/src/main/java/WayofTime/bloodmagic/client/render/entity/layer/LayerAlchemyCircle.java b/src/main/java/WayofTime/bloodmagic/client/render/entity/layer/LayerAlchemyCircle.java new file mode 100644 index 00000000..f2148ee2 --- /dev/null +++ b/src/main/java/WayofTime/bloodmagic/client/render/entity/layer/LayerAlchemyCircle.java @@ -0,0 +1,87 @@ +package WayofTime.bloodmagic.client.render.entity.layer; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.VertexBuffer; +import net.minecraft.client.renderer.entity.layers.LayerRenderer; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import WayofTime.bloodmagic.entity.mob.EntityCorruptedSheep; + +@SideOnly(Side.CLIENT) +public class LayerAlchemyCircle implements LayerRenderer +{ + private static final ResourceLocation ARRAY_TEXTURE = new ResourceLocation("bloodmagic", "textures/models/AlchemyArrays/FastMinerSigil.png"); + + float rotationspeed = 10; + + public LayerAlchemyCircle() + { + + } + + @Override + public void doRenderLayer(EntityCorruptedSheep demon, float limbSwing, float limbSwingAmount, float partialTicks, float ageInTicks, float netHeadYaw, float headPitch, float scale) + { + if (demon.getCastTimer() <= 0) + { + return; + } + + Tessellator tessellator = Tessellator.getInstance(); + VertexBuffer wr = tessellator.getBuffer(); + + GlStateManager.pushMatrix(); + float rot = (float) this.rotationspeed * (partialTicks + demon.ticksExisted); + float secondaryRot = 0; + + float size = 3.0F; + + // Bind the texture to the circle + Minecraft.getMinecraft().renderEngine.bindTexture(ARRAY_TEXTURE); + + GlStateManager.disableCull(); + GlStateManager.enableBlend(); + GlStateManager.blendFunc(770, 1); + GlStateManager.translate(0, 1.5, 0); + GlStateManager.rotate(90.0f, 1, 0, 0); + + GlStateManager.pushMatrix(); +// GlStateManager.translate(0, 0.5f, 0); + + GlStateManager.pushMatrix(); + GlStateManager.rotate(rot, 0, 0, 1); + GlStateManager.rotate(secondaryRot, 1, 0, 0); + GlStateManager.rotate(secondaryRot * 0.45812f, 0, 0, 1); + double var31 = 0.0D; + double var33 = 1.0D; + double var35 = 0; + double var37 = 1; + + GlStateManager.color(1f, 1f, 1f, 1f); + wr.begin(7, DefaultVertexFormats.POSITION_TEX); + // wr.setBrightness(200); + wr.pos(size / 2f, size / 2f, 0.0D).tex(var33, var37).endVertex(); + wr.pos(size / 2f, -size / 2f, 0.0D).tex(var33, var35).endVertex(); + wr.pos(-size / 2f, -size / 2f, 0.0D).tex(var31, var35).endVertex(); + wr.pos(-size / 2f, size / 2f, 0.0D).tex(var31, var37).endVertex(); + tessellator.draw(); + + GlStateManager.popMatrix(); + + GlStateManager.disableBlend(); + GlStateManager.enableCull(); + + GlStateManager.popMatrix(); + GlStateManager.popMatrix(); + } + + @Override + public boolean shouldCombineTextures() + { + return false; + } +} \ No newline at end of file diff --git a/src/main/java/WayofTime/bloodmagic/entity/ai/EntityAIEatAndCorruptBlock.java b/src/main/java/WayofTime/bloodmagic/entity/ai/EntityAIEatAndCorruptBlock.java new file mode 100644 index 00000000..6c95a68a --- /dev/null +++ b/src/main/java/WayofTime/bloodmagic/entity/ai/EntityAIEatAndCorruptBlock.java @@ -0,0 +1,105 @@ +package WayofTime.bloodmagic.entity.ai; + +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.ai.EntityAIBase; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import WayofTime.bloodmagic.entity.mob.EntityAspectedDemonBase; +import WayofTime.bloodmagic.inversion.CorruptionHandler; + +public class EntityAIEatAndCorruptBlock extends EntityAIBase +{ + /** The entity owner of this AITask */ + private final EntityAspectedDemonBase grassEaterEntity; + /** The world the grass eater entity is eating from */ + private final World world; + /** Number of ticks since the entity started to eat grass */ + int eatingGrassTimer; + + public EntityAIEatAndCorruptBlock(EntityAspectedDemonBase entity) + { + this.grassEaterEntity = entity; + this.world = entity.worldObj; + this.setMutexBits(7); + } + + /** + * Returns whether the EntityAIBase should begin execution. + */ + public boolean shouldExecute() + { + if (this.grassEaterEntity.getRNG().nextInt(50) != 0) + { + return false; + } else + { + BlockPos pos = new BlockPos(this.grassEaterEntity.posX, this.grassEaterEntity.posY, this.grassEaterEntity.posZ).down(); + IBlockState offsetState = world.getBlockState(pos); + Block offsetBlock = offsetState.getBlock(); + return CorruptionHandler.isBlockCorruptible(world, grassEaterEntity.getType(), pos, offsetState, offsetBlock); + } + } + + /** + * Execute a one shot task or start executing a continuous task + */ + public void startExecuting() + { + this.eatingGrassTimer = 40; + this.world.setEntityState(this.grassEaterEntity, (byte) 10); + this.grassEaterEntity.getNavigator().clearPathEntity(); + } + + /** + * Resets the task + */ + public void resetTask() + { + this.eatingGrassTimer = 0; + } + + /** + * Returns whether an in-progress EntityAIBase should continue executing + */ + public boolean continueExecuting() + { + return this.eatingGrassTimer > 0; + } + + /** + * Number of ticks since the entity started to eat grass + */ + public int getEatingGrassTimer() + { + return this.eatingGrassTimer; + } + + /** + * Updates the task + */ + public void updateTask() + { + this.eatingGrassTimer = Math.max(0, this.eatingGrassTimer - 1); + + if (this.eatingGrassTimer == 4) + { + BlockPos blockpos = new BlockPos(this.grassEaterEntity.posX, this.grassEaterEntity.posY, this.grassEaterEntity.posZ); + + BlockPos offsetPos = blockpos.down(); + IBlockState offsetState = world.getBlockState(offsetPos); + Block offsetBlock = offsetState.getBlock(); + + if (CorruptionHandler.isBlockCorruptible(world, grassEaterEntity.getType(), offsetPos, offsetState, offsetBlock)) + { +// if (this.world.getGameRules().getBoolean("mobGriefing")) + { + this.world.playEvent(2001, offsetPos, Block.getIdFromBlock(offsetBlock)); + CorruptionHandler.corruptSurroundingBlocks(world, grassEaterEntity.getType(), offsetPos, 2, 0.5, 0.5); + } + + this.grassEaterEntity.eatGrassBonus(); + } + } + } +} \ No newline at end of file diff --git a/src/main/java/WayofTime/bloodmagic/entity/ai/EntityAIProtectAlly.java b/src/main/java/WayofTime/bloodmagic/entity/ai/EntityAIProtectAlly.java new file mode 100644 index 00000000..ad46d8ca --- /dev/null +++ b/src/main/java/WayofTime/bloodmagic/entity/ai/EntityAIProtectAlly.java @@ -0,0 +1,107 @@ +package WayofTime.bloodmagic.entity.ai; + +import java.util.List; + +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.ai.EntityAIBase; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.world.World; +import WayofTime.bloodmagic.entity.mob.EntityAspectedDemonBase; +import WayofTime.bloodmagic.entity.mob.EntityCorruptedSheep; + +public class EntityAIProtectAlly extends EntityAIBase +{ + /** The entity owner of this AITask */ + private final EntityCorruptedSheep entity; + /** The world the grass eater entity is eating from */ + private final World world; + /** Number of ticks since the entity started to eat grass */ + int castTimer; + + public EntityAIProtectAlly(EntityCorruptedSheep entity) + { + this.entity = entity; + this.world = entity.worldObj; + this.setMutexBits(7); + } + + public int getCastTimer() + { + return this.castTimer; + } + + /** + * Returns whether the EntityAIBase should begin execution. + */ + @Override + public boolean shouldExecute() + { + AxisAlignedBB bb = new AxisAlignedBB(entity.posX - 0.5, entity.posY - 0.5, entity.posZ - 0.5, entity.posX + 0.5, entity.posY + 0.5, entity.posZ + 0.5).expandXyz(5); + List list = world.getEntitiesWithinAABB(EntityLivingBase.class, bb, new EntityAspectedDemonBase.WillTypePredicate(entity.getType())); + for (EntityLivingBase testEntity : list) + { + if (testEntity != this.entity) + { + if (this.entity.canProtectAlly(testEntity)) + { + return true; + } + } + } + + return false; + } + + /** + * Execute a one shot task or start executing a continuous task + */ + @Override + public void startExecuting() + { + this.castTimer = 100; + this.world.setEntityState(this.entity, (byte) 53); + this.entity.getNavigator().clearPathEntity(); + } + + /** + * Resets the task + */ + @Override + public void resetTask() + { + this.castTimer = 0; + } + + /** + * Returns whether an in-progress EntityAIBase should continue executing + */ + @Override + public boolean continueExecuting() + { + return castTimer > 0; + } + + /** + * Updates the task + */ + @Override + public void updateTask() + { + this.castTimer = Math.max(0, this.castTimer - 1); + if (castTimer == 0) + { + AxisAlignedBB bb = new AxisAlignedBB(entity.posX - 0.5, entity.posY - 0.5, entity.posZ - 0.5, entity.posX + 0.5, entity.posY + 0.5, entity.posZ + 0.5).expandXyz(5); + List list = world.getEntitiesWithinAABB(EntityLivingBase.class, bb, new EntityAspectedDemonBase.WillTypePredicate(entity.getType())); + for (EntityLivingBase testEntity : list) + { + if (testEntity != this.entity) + { + if (this.entity.applyProtectionToAlly(testEntity)) + { + return; + } + } + } + } + } +} \ No newline at end of file diff --git a/src/main/java/WayofTime/bloodmagic/entity/mob/EntityAspectedDemonBase.java b/src/main/java/WayofTime/bloodmagic/entity/mob/EntityAspectedDemonBase.java index 2768df1e..212100eb 100644 --- a/src/main/java/WayofTime/bloodmagic/entity/mob/EntityAspectedDemonBase.java +++ b/src/main/java/WayofTime/bloodmagic/entity/mob/EntityAspectedDemonBase.java @@ -1,5 +1,7 @@ package WayofTime.bloodmagic.entity.mob; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.SharedMonsterAttributes; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.datasync.DataParameter; import net.minecraft.network.datasync.EntityDataManager; @@ -10,6 +12,8 @@ import WayofTime.bloodmagic.api.Constants; import WayofTime.bloodmagic.api.soul.EnumDemonWillType; import WayofTime.bloodmagic.gson.Serializers; +import com.google.common.base.Predicate; + public abstract class EntityAspectedDemonBase extends EntityDemonBase { protected static final DataParameter TYPE = EntityDataManager.createKey(EntityAspectedDemonBase.class, Serializers.WILL_TYPE_SERIALIZER); @@ -41,6 +45,128 @@ public abstract class EntityAspectedDemonBase extends EntityDemonBase return 0; } + public double getBaseHP(EnumDemonWillType type) + { + double baseHP = 40; + + switch (type) + { + case DEFAULT: + break; + case CORROSIVE: + break; + case DESTRUCTIVE: + break; + case VENGEFUL: + baseHP *= 0.8; + break; + case STEADFAST: + baseHP *= 1.25; + break; + } + + return baseHP; + } + + public double getBaseMeleeDamage(EnumDemonWillType type) + { + double baseDamage = 8; + + switch (type) + { + case DEFAULT: + break; + case CORROSIVE: + baseDamage *= 0.8; + break; + case DESTRUCTIVE: + baseDamage *= 1.5; + break; + case VENGEFUL: + baseDamage *= 0.8; + break; + case STEADFAST: + baseDamage *= 0.6; + break; + } + + return baseDamage; + } + + public double getBaseSpeed(EnumDemonWillType type) + { + double baseSpeed = 0.27; + + switch (type) + { + case DEFAULT: + break; + case CORROSIVE: + break; + case DESTRUCTIVE: + break; + case VENGEFUL: + baseSpeed *= 1.3; + break; + case STEADFAST: + break; + } + + return baseSpeed; + } + + public double getBaseSprintModifier(EnumDemonWillType type) + { + double baseSprint = 1; + + switch (type) + { + case DEFAULT: + break; + case CORROSIVE: + break; + case DESTRUCTIVE: + break; + case VENGEFUL: + baseSprint *= 1.2; + break; + case STEADFAST: + break; + } + + return baseSprint; + } + + public double getBaseKnockbackResist(EnumDemonWillType type) + { + double baseKnockback = 0; + + switch (type) + { + case DEFAULT: + break; + case CORROSIVE: + break; + case DESTRUCTIVE: + break; + case VENGEFUL: + break; + case STEADFAST: + baseKnockback += 0.35; + break; + } + + return baseKnockback; + } + + public void applyEntityAttributes(EnumDemonWillType type) + { + this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(this.getBaseHP(type)); + this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(this.getBaseSpeed(type)); + this.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).setBaseValue(this.getBaseMeleeDamage(type)); + this.getEntityAttribute(SharedMonsterAttributes.KNOCKBACK_RESISTANCE).setBaseValue(this.getBaseKnockbackResist(type)); + } + @Override public boolean attackEntityFrom(DamageSource source, float amount) { @@ -75,6 +201,8 @@ public abstract class EntityAspectedDemonBase extends EntityDemonBase public void setType(EnumDemonWillType type) { this.dataManager.set(TYPE, type); + this.applyEntityAttributes(type); + this.setCombatTask(); } @Override @@ -98,4 +226,55 @@ public abstract class EntityAspectedDemonBase extends EntityDemonBase setType(EnumDemonWillType.valueOf(tag.getString(Constants.NBT.WILL_TYPE))); } } + + public class TeamAttackPredicate implements Predicate + { + private final EntityAspectedDemonBase demon; + + public TeamAttackPredicate(EntityAspectedDemonBase demon) + { + this.demon = demon; + } + + //Returns true if this mob can attack the inputted mob. + @Override + public boolean apply(EntityLivingBase input) + { + if (input instanceof EntityAspectedDemonBase) + { + if (((EntityAspectedDemonBase) input).getType() == demon.getType()) + { + return false; + } + } + + return input != null; + } + } + + //Returns true if the inputted mob is on the same team. + public static class WillTypePredicate implements Predicate + { + private final EnumDemonWillType type; + + public WillTypePredicate(EnumDemonWillType type) + { + this.type = type; + } + + //Returns true if this mob is the same type. + @Override + public boolean apply(EntityLivingBase input) + { + if (input instanceof EntityAspectedDemonBase) + { + if (((EntityAspectedDemonBase) input).getType() == type) + { + return true; + } + } + + return false; + } + } } diff --git a/src/main/java/WayofTime/bloodmagic/entity/mob/EntityCorruptedSheep.java b/src/main/java/WayofTime/bloodmagic/entity/mob/EntityCorruptedSheep.java index ee061adf..828ca982 100644 --- a/src/main/java/WayofTime/bloodmagic/entity/mob/EntityCorruptedSheep.java +++ b/src/main/java/WayofTime/bloodmagic/entity/mob/EntityCorruptedSheep.java @@ -6,19 +6,19 @@ import java.util.Random; import javax.annotation.Nullable; +import lombok.Getter; import net.minecraft.block.Block; +import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.IEntityLivingData; -import net.minecraft.entity.SharedMonsterAttributes; -import net.minecraft.entity.ai.EntityAIEatGrass; +import net.minecraft.entity.ai.EntityAIAttackMelee; import net.minecraft.entity.ai.EntityAILookIdle; -import net.minecraft.entity.ai.EntityAIPanic; +import net.minecraft.entity.ai.EntityAINearestAttackableTarget; import net.minecraft.entity.ai.EntityAISwimming; -import net.minecraft.entity.ai.EntityAITempt; import net.minecraft.entity.ai.EntityAIWander; import net.minecraft.entity.ai.EntityAIWatchClosest; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; -import net.minecraft.init.Items; +import net.minecraft.init.MobEffects; import net.minecraft.init.SoundEvents; import net.minecraft.item.EnumDyeColor; import net.minecraft.item.Item; @@ -27,7 +27,7 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.datasync.DataParameter; import net.minecraft.network.datasync.DataSerializers; import net.minecraft.network.datasync.EntityDataManager; -import net.minecraft.util.EnumHand; +import net.minecraft.potion.PotionEffect; import net.minecraft.util.SoundEvent; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; @@ -36,6 +36,9 @@ import net.minecraft.world.World; import net.minecraftforge.common.IShearable; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import WayofTime.bloodmagic.api.soul.EnumDemonWillType; +import WayofTime.bloodmagic.entity.ai.EntityAIEatAndCorruptBlock; +import WayofTime.bloodmagic.entity.ai.EntityAIProtectAlly; import com.google.common.collect.Maps; @@ -49,35 +52,69 @@ public class EntityCorruptedSheep extends EntityAspectedDemonBase implements ISh * handleHealthUpdate and counts down with each tick. */ private int sheepTimer; - private EntityAIEatGrass entityAIEatGrass; //TODO: Change to a new AI + + @Getter + private int castTimer = 0; + private EntityAIEatAndCorruptBlock entityAIEatGrass; + private EntityAIProtectAlly entityAIProtectAlly; + private EntityAIAttackMelee aiAttackOnCollide; + + private final int attackPriority = 3; + + public int protectionCooldown = 0; + public static int maxProtectionCooldown = 90 * 20; //90 second cooldown public static float[] getDyeRgb(EnumDyeColor dyeColor) { return (float[]) DYE_TO_RGB.get(dyeColor); } - public EntityCorruptedSheep(World worldIn) + public EntityCorruptedSheep(World world) { - super(worldIn); + this(world, EnumDemonWillType.DEFAULT); + } + + public EntityCorruptedSheep(World world, EnumDemonWillType type) + { + super(world); this.setSize(0.9F, 1.3F); + + this.setType(type); } protected void initEntityAI() { - this.entityAIEatGrass = new EntityAIEatGrass(this); + this.entityAIEatGrass = new EntityAIEatAndCorruptBlock(this); + this.entityAIProtectAlly = new EntityAIProtectAlly(this); + this.tasks.addTask(0, new EntityAISwimming(this)); - this.tasks.addTask(1, new EntityAIPanic(this, 1.25D)); - this.tasks.addTask(3, new EntityAITempt(this, 1.1D, Items.WHEAT, false)); + this.tasks.addTask(2, entityAIProtectAlly); this.tasks.addTask(5, this.entityAIEatGrass); this.tasks.addTask(6, new EntityAIWander(this, 1.0D)); this.tasks.addTask(7, new EntityAIWatchClosest(this, EntityPlayer.class, 6.0F)); this.tasks.addTask(8, new EntityAILookIdle(this)); + + this.targetTasks.addTask(1, new EntityAINearestAttackableTarget(this, EntityPlayer.class, true)); + this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, EntityLivingBase.class, 10, true, false, new EntityAspectedDemonBase.TeamAttackPredicate(this))); + } + + @Override + public void setCombatTask() + { + if (aiAttackOnCollide != null) + { + this.tasks.removeTask(aiAttackOnCollide); + } + + aiAttackOnCollide = new EntityAIAttackMelee(this, this.getBaseSprintModifier(getType()), false); + this.tasks.addTask(attackPriority, aiAttackOnCollide); } @Override protected void updateAITasks() { this.sheepTimer = this.entityAIEatGrass.getEatingGrassTimer(); + this.castTimer = this.entityAIProtectAlly.getCastTimer(); super.updateAITasks(); } @@ -87,18 +124,57 @@ public class EntityCorruptedSheep extends EntityAspectedDemonBase implements ISh if (this.worldObj.isRemote) { this.sheepTimer = Math.max(0, this.sheepTimer - 1); + this.castTimer = Math.max(0, castTimer - 1); + if (this.castTimer == 70) + { + this.playSound(this.getHurtSound(), this.getSoundVolume() * 2, this.getSoundPitch()); + } } + this.protectionCooldown = Math.max(0, this.protectionCooldown - 1); + super.onLivingUpdate(); } - @Override - protected void applyEntityAttributes() + public boolean canProtectAlly(EntityLivingBase entity) { - super.applyEntityAttributes(); - this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(30); - this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0.25); - this.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).setBaseValue(6); + return this.protectionCooldown <= 0 && entity.getHealth() < entity.getMaxHealth() && !entity.isPotionActive(MobEffects.RESISTANCE); + } + + public boolean applyProtectionToAlly(EntityLivingBase entity) + { + if (canProtectAlly(entity)) + { + entity.addPotionEffect(new PotionEffect(MobEffects.RESISTANCE, 20 * 20, 3)); + this.protectionCooldown = maxProtectionCooldown; + } + + return false; + } + + public double getBaseHP(EnumDemonWillType type) + { + return super.getBaseHP(type) * 0.75; + } + + public double getBaseMeleeDamage(EnumDemonWillType type) + { + return super.getBaseMeleeDamage(type) * 0.75; + } + + public double getBaseSpeed(EnumDemonWillType type) + { + return super.getBaseSpeed(type); + } + + public double getBaseSprintModifier(EnumDemonWillType type) + { + return super.getBaseSprintModifier(type); + } + + public double getBaseKnockbackResist(EnumDemonWillType type) + { + return super.getBaseKnockbackResist(type) + 0.2; } public double getMeleeResist() @@ -125,6 +201,9 @@ public class EntityCorruptedSheep extends EntityAspectedDemonBase implements ISh if (id == 10) { this.sheepTimer = 40; + } else if (id == 53) + { + this.castTimer = 100; } else { super.handleStatusUpdate(id); @@ -151,19 +230,21 @@ public class EntityCorruptedSheep extends EntityAspectedDemonBase implements ISh } @Override - public void writeEntityToNBT(NBTTagCompound compound) + public void writeEntityToNBT(NBTTagCompound tag) { - super.writeEntityToNBT(compound); - compound.setBoolean("Sheared", this.getSheared()); - compound.setByte("Color", (byte) this.getFleeceColor().getMetadata()); + super.writeEntityToNBT(tag); + tag.setBoolean("Sheared", this.getSheared()); + tag.setByte("Color", (byte) this.getFleeceColor().getMetadata()); + tag.setInteger("protection", this.protectionCooldown); } @Override - public void readEntityFromNBT(NBTTagCompound compound) + public void readEntityFromNBT(NBTTagCompound tag) { - super.readEntityFromNBT(compound); - this.setSheared(compound.getBoolean("Sheared")); - this.setFleeceColor(EnumDyeColor.byMetadata(compound.getByte("Color"))); + super.readEntityFromNBT(tag); + this.setSheared(tag.getBoolean("Sheared")); + this.setFleeceColor(EnumDyeColor.byMetadata(tag.getByte("Color"))); + this.protectionCooldown = tag.getInteger("protection"); } @Override diff --git a/src/main/java/WayofTime/bloodmagic/entity/mob/EntityCorruptedZombie.java b/src/main/java/WayofTime/bloodmagic/entity/mob/EntityCorruptedZombie.java index 0e70e99d..34b0825e 100644 --- a/src/main/java/WayofTime/bloodmagic/entity/mob/EntityCorruptedZombie.java +++ b/src/main/java/WayofTime/bloodmagic/entity/mob/EntityCorruptedZombie.java @@ -51,9 +51,9 @@ public class EntityCorruptedZombie extends EntityAspectedDemonBase this.tasks.addTask(6, new EntityAIMoveThroughVillage(this, 1.0D, false)); this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, true, new Class[] { EntityPigZombie.class })); - this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, EntityPlayer.class, true)); - this.targetTasks.addTask(3, new EntityAINearestAttackableTarget(this, EntityVillager.class, false)); - this.targetTasks.addTask(3, new EntityAINearestAttackableTarget(this, EntityIronGolem.class, true)); + this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, EntityPlayer.class, true)); + this.targetTasks.addTask(3, new EntityAINearestAttackableTarget(this, EntityVillager.class, false)); + this.targetTasks.addTask(3, new EntityAINearestAttackableTarget(this, EntityIronGolem.class, true)); this.setCombatTask(); // this.targetTasks.addTask(8, new EntityAINearestAttackableTarget(this, EntityMob.class, 10, true, false, new TargetPredicate(this))); diff --git a/src/main/java/WayofTime/bloodmagic/inversion/CorruptionHandler.java b/src/main/java/WayofTime/bloodmagic/inversion/CorruptionHandler.java index 9dd39e66..44b3af7e 100644 --- a/src/main/java/WayofTime/bloodmagic/inversion/CorruptionHandler.java +++ b/src/main/java/WayofTime/bloodmagic/inversion/CorruptionHandler.java @@ -60,8 +60,47 @@ public class CorruptionHandler return false; } - public static boolean corruptSurroundingBlocks(World world, EnumDemonWillType type, BlockPos centerPos, int radius) + /** + * + * @param world + * @param type + * @param centerPos + * @param radius + * @param featheringChance + * Chance that the block within the featheringDepth is NOT altered. + * @param featheringDepth + * @return + */ + public static boolean corruptSurroundingBlocks(World world, EnumDemonWillType type, BlockPos centerPos, int radius, double featheringChance, double featheringDepth) { + for (int i = -radius; i <= radius; i++) + { + for (int j = -radius; j <= radius; j++) + { + for (int k = -radius; k <= radius; k++) + { + if (i * i + j * j + k * k > (radius + 0.5) * (radius + 0.5)) + { + continue; + } + + if (featheringChance > 0 && i * i + j * j + k * k > (radius - featheringDepth + 0.5) * (radius - featheringDepth + 0.5) && world.rand.nextDouble() < featheringChance) + { + continue; + } + + if (world.isAirBlock(centerPos)) + { + continue; + } + + BlockPos offsetPos = centerPos.add(i, j, k); + IBlockState offsetState = world.getBlockState(offsetPos); + Block offsetBlock = offsetState.getBlock(); + corruptBlock(world, type, offsetPos, offsetState, offsetBlock); + } + } + } return false; } } diff --git a/src/main/java/WayofTime/bloodmagic/item/sigil/ItemSigilDivination.java b/src/main/java/WayofTime/bloodmagic/item/sigil/ItemSigilDivination.java index 441c1ca9..7420b276 100644 --- a/src/main/java/WayofTime/bloodmagic/item/sigil/ItemSigilDivination.java +++ b/src/main/java/WayofTime/bloodmagic/item/sigil/ItemSigilDivination.java @@ -14,6 +14,7 @@ import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; import WayofTime.bloodmagic.api.altar.IBloodAltar; import WayofTime.bloodmagic.api.iface.IAltarReader; +import WayofTime.bloodmagic.api.soul.EnumDemonWillType; import WayofTime.bloodmagic.api.util.helper.NetworkHelper; import WayofTime.bloodmagic.api.util.helper.PlayerHelper; import WayofTime.bloodmagic.entity.mob.EntityCorruptedSheep; @@ -42,7 +43,7 @@ public class ItemSigilDivination extends ItemSigilBase implements IAltarReader if (!world.isRemote) { - EntityCorruptedSheep fred = new EntityCorruptedSheep(world); + EntityCorruptedSheep fred = new EntityCorruptedSheep(world, EnumDemonWillType.DESTRUCTIVE); fred.setPosition(player.posX, player.posY, player.posZ); world.spawnEntityInWorld(fred); } diff --git a/src/main/java/WayofTime/bloodmagic/registry/ModCorruptionBlocks.java b/src/main/java/WayofTime/bloodmagic/registry/ModCorruptionBlocks.java new file mode 100644 index 00000000..7e4c1cbc --- /dev/null +++ b/src/main/java/WayofTime/bloodmagic/registry/ModCorruptionBlocks.java @@ -0,0 +1,18 @@ +package WayofTime.bloodmagic.registry; + +import net.minecraft.init.Blocks; +import WayofTime.bloodmagic.api.soul.EnumDemonWillType; +import WayofTime.bloodmagic.inversion.CorruptionHandler; + +public class ModCorruptionBlocks +{ + public static void init() + { + for (EnumDemonWillType type : EnumDemonWillType.values()) + { + CorruptionHandler.registerBlockCorruption(type, Blocks.STONE, 0, ModBlocks.DEMON_EXTRAS.getStateFromMeta(type.ordinal())); + CorruptionHandler.registerBlockCorruption(type, Blocks.GRASS, 0, ModBlocks.DEMON_EXTRAS.getStateFromMeta(type.ordinal())); + CorruptionHandler.registerBlockCorruption(type, Blocks.DIRT, 0, ModBlocks.DEMON_EXTRAS.getStateFromMeta(type.ordinal())); + } + } +}