Updated the hp/damage/etc logic of the corrupted mobs in general, and made it so the sheep will cast resistance on hurt allies when nearby on a cooldown.

Added an alchemy array layer (WIP) for the sheep when it is casting a "spell".
This commit is contained in:
WayofTime 2016-09-18 18:44:18 -04:00
parent cbd2609fe2
commit d6c1d59e5d
11 changed files with 652 additions and 31 deletions

View file

@ -31,6 +31,7 @@ import WayofTime.bloodmagic.proxy.CommonProxy;
import WayofTime.bloodmagic.registry.ModArmourTrackers; import WayofTime.bloodmagic.registry.ModArmourTrackers;
import WayofTime.bloodmagic.registry.ModBlocks; import WayofTime.bloodmagic.registry.ModBlocks;
import WayofTime.bloodmagic.registry.ModCompatibility; import WayofTime.bloodmagic.registry.ModCompatibility;
import WayofTime.bloodmagic.registry.ModCorruptionBlocks;
import WayofTime.bloodmagic.registry.ModEntities; import WayofTime.bloodmagic.registry.ModEntities;
import WayofTime.bloodmagic.registry.ModItems; import WayofTime.bloodmagic.registry.ModItems;
import WayofTime.bloodmagic.registry.ModPotions; import WayofTime.bloodmagic.registry.ModPotions;
@ -131,6 +132,7 @@ public class BloodMagic
ModArmourTrackers.init(); ModArmourTrackers.init();
ModCompatibility.loadCompat(ICompatibility.InitializationPhase.INIT); ModCompatibility.loadCompat(ICompatibility.InitializationPhase.INIT);
NetworkRegistry.INSTANCE.registerGuiHandler(BloodMagic.instance, new GuiHandler()); NetworkRegistry.INSTANCE.registerGuiHandler(BloodMagic.instance, new GuiHandler());
ModCorruptionBlocks.init();
proxy.init(); proxy.init();
} }

View file

@ -5,6 +5,7 @@ import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly; 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.LayerCorruptedSheepWool;
import WayofTime.bloodmagic.client.render.entity.layer.LayerWill; import WayofTime.bloodmagic.client.render.entity.layer.LayerWill;
import WayofTime.bloodmagic.client.render.model.ModelCorruptedSheep; import WayofTime.bloodmagic.client.render.model.ModelCorruptedSheep;
@ -22,6 +23,7 @@ public class RenderCorruptedSheep extends RenderLiving<EntityCorruptedSheep>
this.addLayer(new LayerCorruptedSheepWool(this)); this.addLayer(new LayerCorruptedSheepWool(this));
this.addLayer(new LayerWill<EntityCorruptedSheep>(this, new ModelCorruptedSheep(1.1f))); this.addLayer(new LayerWill<EntityCorruptedSheep>(this, new ModelCorruptedSheep(1.1f)));
this.addLayer(new LayerWill<EntityCorruptedSheep>(this, new ModelCorruptedSheep2(1.1f))); this.addLayer(new LayerWill<EntityCorruptedSheep>(this, new ModelCorruptedSheep2(1.1f)));
this.addLayer(new LayerAlchemyCircle<EntityCorruptedSheep>());
} }
@Override @Override

View file

@ -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<T extends EntityCorruptedSheep> implements LayerRenderer<T>
{
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;
}
}

View file

@ -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();
}
}
}
}

View file

@ -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<EntityLivingBase> 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<EntityLivingBase> 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;
}
}
}
}
}
}

View file

@ -1,5 +1,7 @@
package WayofTime.bloodmagic.entity.mob; package WayofTime.bloodmagic.entity.mob;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.datasync.DataParameter; import net.minecraft.network.datasync.DataParameter;
import net.minecraft.network.datasync.EntityDataManager; import net.minecraft.network.datasync.EntityDataManager;
@ -10,6 +12,8 @@ import WayofTime.bloodmagic.api.Constants;
import WayofTime.bloodmagic.api.soul.EnumDemonWillType; import WayofTime.bloodmagic.api.soul.EnumDemonWillType;
import WayofTime.bloodmagic.gson.Serializers; import WayofTime.bloodmagic.gson.Serializers;
import com.google.common.base.Predicate;
public abstract class EntityAspectedDemonBase extends EntityDemonBase public abstract class EntityAspectedDemonBase extends EntityDemonBase
{ {
protected static final DataParameter<EnumDemonWillType> TYPE = EntityDataManager.<EnumDemonWillType>createKey(EntityAspectedDemonBase.class, Serializers.WILL_TYPE_SERIALIZER); protected static final DataParameter<EnumDemonWillType> TYPE = EntityDataManager.<EnumDemonWillType>createKey(EntityAspectedDemonBase.class, Serializers.WILL_TYPE_SERIALIZER);
@ -41,6 +45,128 @@ public abstract class EntityAspectedDemonBase extends EntityDemonBase
return 0; 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 @Override
public boolean attackEntityFrom(DamageSource source, float amount) public boolean attackEntityFrom(DamageSource source, float amount)
{ {
@ -75,6 +201,8 @@ public abstract class EntityAspectedDemonBase extends EntityDemonBase
public void setType(EnumDemonWillType type) public void setType(EnumDemonWillType type)
{ {
this.dataManager.set(TYPE, type); this.dataManager.set(TYPE, type);
this.applyEntityAttributes(type);
this.setCombatTask();
} }
@Override @Override
@ -98,4 +226,55 @@ public abstract class EntityAspectedDemonBase extends EntityDemonBase
setType(EnumDemonWillType.valueOf(tag.getString(Constants.NBT.WILL_TYPE))); setType(EnumDemonWillType.valueOf(tag.getString(Constants.NBT.WILL_TYPE)));
} }
} }
public class TeamAttackPredicate implements Predicate<EntityLivingBase>
{
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<EntityLivingBase>
{
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;
}
}
} }

View file

@ -6,19 +6,19 @@ import java.util.Random;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import lombok.Getter;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.IEntityLivingData; import net.minecraft.entity.IEntityLivingData;
import net.minecraft.entity.SharedMonsterAttributes; import net.minecraft.entity.ai.EntityAIAttackMelee;
import net.minecraft.entity.ai.EntityAIEatGrass;
import net.minecraft.entity.ai.EntityAILookIdle; 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.EntityAISwimming;
import net.minecraft.entity.ai.EntityAITempt;
import net.minecraft.entity.ai.EntityAIWander; import net.minecraft.entity.ai.EntityAIWander;
import net.minecraft.entity.ai.EntityAIWatchClosest; import net.minecraft.entity.ai.EntityAIWatchClosest;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks; import net.minecraft.init.Blocks;
import net.minecraft.init.Items; import net.minecraft.init.MobEffects;
import net.minecraft.init.SoundEvents; import net.minecraft.init.SoundEvents;
import net.minecraft.item.EnumDyeColor; import net.minecraft.item.EnumDyeColor;
import net.minecraft.item.Item; 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.DataParameter;
import net.minecraft.network.datasync.DataSerializers; import net.minecraft.network.datasync.DataSerializers;
import net.minecraft.network.datasync.EntityDataManager; 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.SoundEvent;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
@ -36,6 +36,9 @@ import net.minecraft.world.World;
import net.minecraftforge.common.IShearable; import net.minecraftforge.common.IShearable;
import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly; 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; import com.google.common.collect.Maps;
@ -49,35 +52,69 @@ public class EntityCorruptedSheep extends EntityAspectedDemonBase implements ISh
* handleHealthUpdate and counts down with each tick. * handleHealthUpdate and counts down with each tick.
*/ */
private int sheepTimer; 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) public static float[] getDyeRgb(EnumDyeColor dyeColor)
{ {
return (float[]) DYE_TO_RGB.get(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.setSize(0.9F, 1.3F);
this.setType(type);
} }
protected void initEntityAI() 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(0, new EntityAISwimming(this));
this.tasks.addTask(1, new EntityAIPanic(this, 1.25D)); this.tasks.addTask(2, entityAIProtectAlly);
this.tasks.addTask(3, new EntityAITempt(this, 1.1D, Items.WHEAT, false));
this.tasks.addTask(5, this.entityAIEatGrass); this.tasks.addTask(5, this.entityAIEatGrass);
this.tasks.addTask(6, new EntityAIWander(this, 1.0D)); this.tasks.addTask(6, new EntityAIWander(this, 1.0D));
this.tasks.addTask(7, new EntityAIWatchClosest(this, EntityPlayer.class, 6.0F)); this.tasks.addTask(7, new EntityAIWatchClosest(this, EntityPlayer.class, 6.0F));
this.tasks.addTask(8, new EntityAILookIdle(this)); this.tasks.addTask(8, new EntityAILookIdle(this));
this.targetTasks.addTask(1, new EntityAINearestAttackableTarget<EntityPlayer>(this, EntityPlayer.class, true));
this.targetTasks.addTask(2, new EntityAINearestAttackableTarget<EntityLivingBase>(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 @Override
protected void updateAITasks() protected void updateAITasks()
{ {
this.sheepTimer = this.entityAIEatGrass.getEatingGrassTimer(); this.sheepTimer = this.entityAIEatGrass.getEatingGrassTimer();
this.castTimer = this.entityAIProtectAlly.getCastTimer();
super.updateAITasks(); super.updateAITasks();
} }
@ -87,18 +124,57 @@ public class EntityCorruptedSheep extends EntityAspectedDemonBase implements ISh
if (this.worldObj.isRemote) if (this.worldObj.isRemote)
{ {
this.sheepTimer = Math.max(0, this.sheepTimer - 1); 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(); super.onLivingUpdate();
} }
@Override public boolean canProtectAlly(EntityLivingBase entity)
protected void applyEntityAttributes()
{ {
super.applyEntityAttributes(); return this.protectionCooldown <= 0 && entity.getHealth() < entity.getMaxHealth() && !entity.isPotionActive(MobEffects.RESISTANCE);
this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(30); }
this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0.25);
this.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).setBaseValue(6); 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() public double getMeleeResist()
@ -125,6 +201,9 @@ public class EntityCorruptedSheep extends EntityAspectedDemonBase implements ISh
if (id == 10) if (id == 10)
{ {
this.sheepTimer = 40; this.sheepTimer = 40;
} else if (id == 53)
{
this.castTimer = 100;
} else } else
{ {
super.handleStatusUpdate(id); super.handleStatusUpdate(id);
@ -151,19 +230,21 @@ public class EntityCorruptedSheep extends EntityAspectedDemonBase implements ISh
} }
@Override @Override
public void writeEntityToNBT(NBTTagCompound compound) public void writeEntityToNBT(NBTTagCompound tag)
{ {
super.writeEntityToNBT(compound); super.writeEntityToNBT(tag);
compound.setBoolean("Sheared", this.getSheared()); tag.setBoolean("Sheared", this.getSheared());
compound.setByte("Color", (byte) this.getFleeceColor().getMetadata()); tag.setByte("Color", (byte) this.getFleeceColor().getMetadata());
tag.setInteger("protection", this.protectionCooldown);
} }
@Override @Override
public void readEntityFromNBT(NBTTagCompound compound) public void readEntityFromNBT(NBTTagCompound tag)
{ {
super.readEntityFromNBT(compound); super.readEntityFromNBT(tag);
this.setSheared(compound.getBoolean("Sheared")); this.setSheared(tag.getBoolean("Sheared"));
this.setFleeceColor(EnumDyeColor.byMetadata(compound.getByte("Color"))); this.setFleeceColor(EnumDyeColor.byMetadata(tag.getByte("Color")));
this.protectionCooldown = tag.getInteger("protection");
} }
@Override @Override

View file

@ -51,9 +51,9 @@ public class EntityCorruptedZombie extends EntityAspectedDemonBase
this.tasks.addTask(6, new EntityAIMoveThroughVillage(this, 1.0D, false)); 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(1, new EntityAIHurtByTarget(this, true, new Class[] { EntityPigZombie.class }));
this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, EntityPlayer.class, true)); this.targetTasks.addTask(2, new EntityAINearestAttackableTarget<EntityPlayer>(this, EntityPlayer.class, true));
this.targetTasks.addTask(3, new EntityAINearestAttackableTarget(this, EntityVillager.class, false)); this.targetTasks.addTask(3, new EntityAINearestAttackableTarget<EntityVillager>(this, EntityVillager.class, false));
this.targetTasks.addTask(3, new EntityAINearestAttackableTarget(this, EntityIronGolem.class, true)); this.targetTasks.addTask(3, new EntityAINearestAttackableTarget<EntityIronGolem>(this, EntityIronGolem.class, true));
this.setCombatTask(); this.setCombatTask();
// this.targetTasks.addTask(8, new EntityAINearestAttackableTarget<EntityMob>(this, EntityMob.class, 10, true, false, new TargetPredicate(this))); // this.targetTasks.addTask(8, new EntityAINearestAttackableTarget<EntityMob>(this, EntityMob.class, 10, true, false, new TargetPredicate(this)));

View file

@ -60,8 +60,47 @@ public class CorruptionHandler
return false; 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; return false;
} }
} }

View file

@ -14,6 +14,7 @@ import net.minecraft.util.text.TextComponentTranslation;
import net.minecraft.world.World; import net.minecraft.world.World;
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.soul.EnumDemonWillType;
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.entity.mob.EntityCorruptedSheep; import WayofTime.bloodmagic.entity.mob.EntityCorruptedSheep;
@ -42,7 +43,7 @@ public class ItemSigilDivination extends ItemSigilBase implements IAltarReader
if (!world.isRemote) if (!world.isRemote)
{ {
EntityCorruptedSheep fred = new EntityCorruptedSheep(world); EntityCorruptedSheep fred = new EntityCorruptedSheep(world, EnumDemonWillType.DESTRUCTIVE);
fred.setPosition(player.posX, player.posY, player.posZ); fred.setPosition(player.posX, player.posY, player.posZ);
world.spawnEntityInWorld(fred); world.spawnEntityInWorld(fred);
} }

View file

@ -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()));
}
}
}