
I redone where the items/blocsks are stored and how the configs are handled to clean up it and give space. You can change the config line to AWWayofTime if you want to keep the compatibility with old configs. Now you reference the blocks from the ModBlocks and Items from the ModItems.
512 lines
16 KiB
Java
512 lines
16 KiB
Java
package WayofTime.alchemicalWizardry.common.entity.mob;
|
|
|
|
import WayofTime.alchemicalWizardry.common.AlchemicalWizardry;
|
|
import WayofTime.alchemicalWizardry.common.EntityAITargetAggro;
|
|
import WayofTime.alchemicalWizardry.common.ModItems;
|
|
import WayofTime.alchemicalWizardry.common.entity.projectile.IceProjectile;
|
|
import net.minecraft.block.Block;
|
|
import net.minecraft.block.BlockColored;
|
|
import net.minecraft.entity.*;
|
|
import net.minecraft.entity.ai.*;
|
|
import net.minecraft.entity.monster.EntityCreeper;
|
|
import net.minecraft.entity.monster.EntityGhast;
|
|
import net.minecraft.entity.passive.EntityAnimal;
|
|
import net.minecraft.entity.passive.EntityHorse;
|
|
import net.minecraft.entity.passive.EntityWolf;
|
|
import net.minecraft.entity.player.EntityPlayer;
|
|
import net.minecraft.entity.projectile.EntityArrow;
|
|
import net.minecraft.item.Item;
|
|
import net.minecraft.item.ItemFood;
|
|
import net.minecraft.item.ItemStack;
|
|
import net.minecraft.nbt.NBTTagCompound;
|
|
import net.minecraft.pathfinding.PathEntity;
|
|
import net.minecraft.util.DamageSource;
|
|
import net.minecraft.world.World;
|
|
|
|
public class EntityIceDemon extends EntityDemon implements IRangedAttackMob {
|
|
private EntityAIArrowAttack aiArrowAttack = new EntityAIArrowAttack(this, 1.0D, 30, 50, 15.0F);
|
|
private EntityAIAttackOnCollide aiAttackOnCollide = new EntityAIAttackOnCollide(this, EntityPlayer.class, 1.2D, false);
|
|
|
|
private static float maxTamedHealth = 50.0F;
|
|
private static float maxUntamedHealth = 30.0F;
|
|
|
|
public EntityIceDemon(World par1World)
|
|
{
|
|
super(par1World, AlchemicalWizardry.entityIceDemonID);
|
|
this.setSize(0.5F, 2.0F);
|
|
//this.getNavigator().setAvoidsWater(true);
|
|
this.tasks.addTask(1, new EntityAISwimming(this));
|
|
this.tasks.addTask(2, this.aiSit);
|
|
//this.tasks.addTask(3, new EntityAILeapAtTarget(this, 0.4F));
|
|
//this.tasks.addTask(4, new EntityAIAttackOnCollide(this, 1.0D, true));
|
|
this.tasks.addTask(5, new EntityAIFollowOwner(this, 1.0D, 10.0F, 2.0F));
|
|
//this.tasks.addTask(6, new EntityAIMate(this, 1.0D));
|
|
this.tasks.addTask(7, new EntityAIWander(this, 1.0D));
|
|
//this.tasks.addTask(8, new EntityAIBeg(this, 8.0F));
|
|
this.tasks.addTask(9, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F));
|
|
this.tasks.addTask(9, new EntityAILookIdle(this));
|
|
this.targetTasks.addTask(1, new EntityAIOwnerHurtByTarget(this));
|
|
this.targetTasks.addTask(2, new EntityAIOwnerHurtTarget(this));
|
|
this.targetTasks.addTask(3, new EntityAIHurtByTarget(this, true));
|
|
this.targetTasks.addTask(4, new EntityAITargetAggro(this, EntityPlayer.class, 0, false));
|
|
this.setAggro(false);
|
|
//this.targetTasks.addTask(4, new EntityAITargetNonTamed(this, EntitySheep.class, 200, false));
|
|
this.setTamed(false);
|
|
|
|
if (par1World != null && !par1World.isRemote)
|
|
{
|
|
this.setCombatTask();
|
|
}
|
|
|
|
//this.isImmuneToFire = true;
|
|
}
|
|
|
|
@Override
|
|
protected void applyEntityAttributes()
|
|
{
|
|
super.applyEntityAttributes();
|
|
//This line affects the speed of the monster
|
|
this.getEntityAttribute(SharedMonsterAttributes.movementSpeed).setAttribute(0.40000001192092896D);
|
|
|
|
//My guess is that this will alter the max health
|
|
if (this.isTamed())
|
|
{
|
|
this.getEntityAttribute(SharedMonsterAttributes.maxHealth).setAttribute(this.maxTamedHealth);
|
|
} else
|
|
{
|
|
this.getEntityAttribute(SharedMonsterAttributes.maxHealth).setAttribute(this.maxUntamedHealth);
|
|
}
|
|
|
|
//this.func_110148_a(SharedMonsterAttributes.field_111267_a).func_111128_a(10.0D);
|
|
}
|
|
|
|
/**
|
|
* Returns true if the newer Entity AI code should be run
|
|
*/
|
|
public boolean isAIEnabled()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Sets the active target the Task system uses for tracking
|
|
*/
|
|
public void setAttackTarget(EntityLivingBase par1EntityLivingBase)
|
|
{
|
|
super.setAttackTarget(par1EntityLivingBase);
|
|
|
|
if (par1EntityLivingBase == null)
|
|
{
|
|
this.setAngry(false);
|
|
} else if (!this.isTamed())
|
|
{
|
|
this.setAngry(true);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* main AI tick function, replaces updateEntityActionState
|
|
*/
|
|
protected void updateAITick()
|
|
{
|
|
this.dataWatcher.updateObject(18, Float.valueOf(this.getHealth()));
|
|
}
|
|
|
|
protected void entityInit()
|
|
{
|
|
super.entityInit();
|
|
this.dataWatcher.addObject(18, new Float(this.getHealth()));
|
|
this.dataWatcher.addObject(19, new Byte((byte) 0));
|
|
this.dataWatcher.addObject(20, new Byte((byte) BlockColored.getBlockFromDye(1)));
|
|
}
|
|
|
|
/**
|
|
* Plays step sound at given x, y, z for the entity
|
|
*/
|
|
protected void playStepSound(int par1, int par2, int par3, int par4)
|
|
{
|
|
this.playSound("mob.zombie.step", 0.15F, 1.0F);
|
|
}
|
|
|
|
/**
|
|
* (abstract) Protected helper method to write subclass entity data to NBT.
|
|
*/
|
|
public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound)
|
|
{
|
|
super.writeEntityToNBT(par1NBTTagCompound);
|
|
par1NBTTagCompound.setBoolean("Angry", this.isAngry());
|
|
par1NBTTagCompound.setByte("CollarColor", (byte) this.getCollarColor());
|
|
}
|
|
|
|
/**
|
|
* (abstract) Protected helper method to read subclass entity data from NBT.
|
|
*/
|
|
public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound)
|
|
{
|
|
super.readEntityFromNBT(par1NBTTagCompound);
|
|
this.setAngry(par1NBTTagCompound.getBoolean("Angry"));
|
|
|
|
if (par1NBTTagCompound.hasKey("CollarColor"))
|
|
{
|
|
this.setCollarColor(par1NBTTagCompound.getByte("CollarColor"));
|
|
}
|
|
|
|
this.setCombatTask();
|
|
}
|
|
|
|
/**
|
|
* Returns the sound this mob makes while it's alive.
|
|
*/
|
|
protected String getLivingSound()
|
|
{
|
|
return "none";
|
|
}
|
|
|
|
/**
|
|
* Returns the sound this mob makes when it is hurt.
|
|
*/
|
|
protected String getHurtSound()
|
|
{
|
|
return "mob.irongolem.hit";
|
|
}
|
|
|
|
/**
|
|
* Returns the sound this mob makes on death.
|
|
*/
|
|
protected String getDeathSound()
|
|
{
|
|
return "mob.irongolem.death";
|
|
}
|
|
|
|
/**
|
|
* Returns the volume for the sounds this mob makes.
|
|
*/
|
|
protected float getSoundVolume()
|
|
{
|
|
return 0.4F;
|
|
}
|
|
|
|
/**
|
|
* Returns the item ID for the item the mob drops on death.
|
|
*/
|
|
protected int getDropItemId()
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
/**
|
|
* Called frequently so the entity can update its state every tick as required. For example, zombies and skeletons
|
|
* use this to react to sunlight and start to burn.
|
|
*/
|
|
public void onLivingUpdate()
|
|
{
|
|
super.onLivingUpdate();
|
|
int range = 2;
|
|
|
|
for (int i = -range; i <= range; i++)
|
|
{
|
|
for (int j = -range; j <= range; j++)
|
|
{
|
|
for (int k = -range; k <= range; k++)
|
|
{
|
|
if (worldObj.rand.nextFloat() < 0.25f)
|
|
{
|
|
int blockID = worldObj.getBlockId((int) posX + i, (int) posY + j, (int) posZ + k);
|
|
|
|
if (blockID == Block.waterStill.blockID || blockID == Block.waterMoving.blockID)
|
|
{
|
|
worldObj.setBlock((int) posX + i, (int) posY + j, (int) posZ + k, Block.ice.blockID);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Called to update the entity's position/logic.
|
|
*/
|
|
public void onUpdate()
|
|
{
|
|
super.onUpdate();
|
|
}
|
|
|
|
public float getEyeHeight()
|
|
{
|
|
return this.height * 0.8F;
|
|
}
|
|
|
|
/**
|
|
* The speed it takes to move the entityliving's rotationPitch through the faceEntity method. This is only currently
|
|
* use in wolves.
|
|
*/
|
|
public int getVerticalFaceSpeed()
|
|
{
|
|
return this.isSitting() ? 20 : super.getVerticalFaceSpeed();
|
|
}
|
|
|
|
/**
|
|
* Called when the entity is attacked.
|
|
*/
|
|
public boolean attackEntityFrom(DamageSource par1DamageSource, float par2)
|
|
{
|
|
if (this.isEntityInvulnerable())
|
|
{
|
|
return false;
|
|
} else
|
|
{
|
|
Entity entity = par1DamageSource.getEntity();
|
|
this.aiSit.setSitting(false);
|
|
|
|
if (entity != null && !(entity instanceof EntityPlayer) && !(entity instanceof EntityArrow))
|
|
{
|
|
par2 = (par2 + 1.0F) / 2.0F;
|
|
}
|
|
|
|
return super.attackEntityFrom(par1DamageSource, par2);
|
|
}
|
|
}
|
|
|
|
public boolean attackEntityAsMob(Entity par1Entity)
|
|
{
|
|
int i = this.isTamed() ? 4 : 2;
|
|
return par1Entity.attackEntityFrom(DamageSource.causeMobDamage(this), (float) i);
|
|
}
|
|
|
|
public void setTamed(boolean par1)
|
|
{
|
|
super.setTamed(par1);
|
|
|
|
if (par1)
|
|
{
|
|
this.getEntityAttribute(SharedMonsterAttributes.maxHealth).setAttribute(this.maxTamedHealth);
|
|
} else
|
|
{
|
|
this.getEntityAttribute(SharedMonsterAttributes.maxHealth).setAttribute(this.maxUntamedHealth);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Called when a player interacts with a mob. e.g. gets milk from a cow, gets into the saddle on a pig.
|
|
*/
|
|
public boolean interact(EntityPlayer par1EntityPlayer)
|
|
{
|
|
ItemStack itemstack = par1EntityPlayer.inventory.getCurrentItem();
|
|
|
|
if (this.isTamed())
|
|
{
|
|
if (itemstack != null)
|
|
{
|
|
if (Item.itemsList[itemstack.itemID] instanceof ItemFood)
|
|
{
|
|
ItemFood itemfood = (ItemFood) Item.itemsList[itemstack.itemID];
|
|
|
|
if (itemfood.isWolfsFavoriteMeat() && this.dataWatcher.getWatchableObjectFloat(18) < this.maxTamedHealth)
|
|
{
|
|
if (!par1EntityPlayer.capabilities.isCreativeMode)
|
|
{
|
|
--itemstack.stackSize;
|
|
}
|
|
|
|
this.heal((float) itemfood.getHealAmount());
|
|
|
|
if (itemstack.stackSize <= 0)
|
|
{
|
|
par1EntityPlayer.inventory.setInventorySlotContents(par1EntityPlayer.inventory.currentItem, (ItemStack) null);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (par1EntityPlayer.getCommandSenderName().equalsIgnoreCase(this.getOwnerName()) && !this.isBreedingItem(itemstack))
|
|
{
|
|
if (!this.worldObj.isRemote)
|
|
{
|
|
this.aiSit.setSitting(!this.isSitting());
|
|
this.isJumping = false;
|
|
this.setPathToEntity((PathEntity) null);
|
|
this.setTarget((Entity) null);
|
|
this.setAttackTarget((EntityLivingBase) null);
|
|
}
|
|
|
|
this.sendSittingMessageToPlayer(par1EntityPlayer, !this.isSitting());
|
|
}
|
|
} else if (itemstack != null && itemstack.itemID == ModItems.weakBloodOrb.itemID && !this.isAngry() && !this.isAggro())
|
|
{
|
|
if (!par1EntityPlayer.capabilities.isCreativeMode)
|
|
{
|
|
--itemstack.stackSize;
|
|
}
|
|
|
|
if (itemstack.stackSize <= 0)
|
|
{
|
|
par1EntityPlayer.inventory.setInventorySlotContents(par1EntityPlayer.inventory.currentItem, (ItemStack) null);
|
|
}
|
|
|
|
if (!this.worldObj.isRemote)
|
|
{
|
|
if (this.rand.nextInt(1) == 0)
|
|
{
|
|
this.setTamed(true);
|
|
this.setPathToEntity((PathEntity) null);
|
|
this.setAttackTarget((EntityLivingBase) null);
|
|
this.aiSit.setSitting(true);
|
|
this.setHealth(this.maxTamedHealth);
|
|
this.setOwner(par1EntityPlayer.getCommandSenderName());
|
|
this.playTameEffect(true);
|
|
this.worldObj.setEntityState(this, (byte) 7);
|
|
} else
|
|
{
|
|
this.playTameEffect(false);
|
|
this.worldObj.setEntityState(this, (byte) 6);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
return super.interact(par1EntityPlayer);
|
|
}
|
|
|
|
/**
|
|
* Checks if the parameter is an item which this animal can be fed to breed it (wheat, carrots or seeds depending on
|
|
* the animal type)
|
|
*/
|
|
public boolean isBreedingItem(ItemStack par1ItemStack)
|
|
{
|
|
return false;
|
|
//return par1ItemStack == null ? false : (!(Item.itemsList[par1ItemStack.itemID] instanceof ItemFood) ? false : ((ItemFood)Item.itemsList[par1ItemStack.itemID]).isWolfsFavoriteMeat());
|
|
}
|
|
|
|
/**
|
|
* Determines whether this wolf is angry or not.
|
|
*/
|
|
public boolean isAngry()
|
|
{
|
|
return (this.dataWatcher.getWatchableObjectByte(16) & 2) != 0;
|
|
}
|
|
|
|
/**
|
|
* Sets whether this wolf is angry or not.
|
|
*/
|
|
public void setAngry(boolean par1)
|
|
{
|
|
byte b0 = this.dataWatcher.getWatchableObjectByte(16);
|
|
|
|
if (par1)
|
|
{
|
|
this.dataWatcher.updateObject(16, Byte.valueOf((byte) (b0 | 2)));
|
|
} else
|
|
{
|
|
this.dataWatcher.updateObject(16, Byte.valueOf((byte) (b0 & -3)));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return this wolf's collar color.
|
|
*/
|
|
public int getCollarColor()
|
|
{
|
|
return this.dataWatcher.getWatchableObjectByte(20) & 15;
|
|
}
|
|
|
|
/**
|
|
* Set this wolf's collar color.
|
|
*/
|
|
public void setCollarColor(int par1)
|
|
{
|
|
this.dataWatcher.updateObject(20, Byte.valueOf((byte) (par1 & 15)));
|
|
}
|
|
|
|
/**
|
|
* This function is used when two same-species animals in 'love mode' breed to generate the new baby animal.
|
|
*/
|
|
public EntityWolf spawnBabyAnimal(EntityAgeable par1EntityAgeable)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
public void func_70918_i(boolean par1)
|
|
{
|
|
if (par1)
|
|
{
|
|
this.dataWatcher.updateObject(19, Byte.valueOf((byte) 1));
|
|
} else
|
|
{
|
|
this.dataWatcher.updateObject(19, Byte.valueOf((byte) 0));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns true if the mob is currently able to mate with the specified mob.
|
|
*/
|
|
public boolean canMateWith(EntityAnimal par1EntityAnimal)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
public boolean func_70922_bv()
|
|
{
|
|
return this.dataWatcher.getWatchableObjectByte(19) == 1;
|
|
}
|
|
|
|
/**
|
|
* Determines if an entity can be despawned, used on idle far away entities
|
|
*/
|
|
protected boolean canDespawn()
|
|
{
|
|
//return !this.isTamed() && this.ticksExisted > 2400;
|
|
return false;
|
|
}
|
|
|
|
public boolean func_142018_a(EntityLivingBase par1EntityLivingBase, EntityLivingBase par2EntityLivingBase)
|
|
{
|
|
if (!(par1EntityLivingBase instanceof EntityCreeper) && !(par1EntityLivingBase instanceof EntityGhast))
|
|
{
|
|
if (par1EntityLivingBase instanceof EntityIceDemon)
|
|
{
|
|
EntityIceDemon entitywolf = (EntityIceDemon) par1EntityLivingBase;
|
|
|
|
if (entitywolf.isTamed() && entitywolf.func_130012_q() == par2EntityLivingBase)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return par1EntityLivingBase instanceof EntityPlayer && par2EntityLivingBase instanceof EntityPlayer && !((EntityPlayer) par2EntityLivingBase).canAttackPlayer((EntityPlayer) par1EntityLivingBase) ? false : !(par1EntityLivingBase instanceof EntityHorse) || !((EntityHorse) par1EntityLivingBase).isTame();
|
|
} else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public EntityAgeable createChild(EntityAgeable par1EntityAgeable)
|
|
{
|
|
return this.spawnBabyAnimal(par1EntityAgeable);
|
|
}
|
|
|
|
/**
|
|
* Attack the specified entity using a ranged attack.
|
|
*/
|
|
public void attackEntityWithRangedAttack(EntityLivingBase par1EntityLivingBase, float par2)
|
|
{
|
|
double xCoord;
|
|
double yCoord;
|
|
double zCoord;
|
|
IceProjectile hol = new IceProjectile(worldObj, this, par1EntityLivingBase, 1.8f, 0f, 3, 600);
|
|
this.worldObj.spawnEntityInWorld(hol);
|
|
}
|
|
|
|
/**
|
|
* sets this entity's combat AI.
|
|
*/
|
|
public void setCombatTask()
|
|
{
|
|
this.tasks.removeTask(this.aiAttackOnCollide);
|
|
this.tasks.removeTask(this.aiArrowAttack);
|
|
ItemStack itemstack = this.getHeldItem();
|
|
this.tasks.addTask(4, this.aiArrowAttack);
|
|
}
|
|
} |