    001    package net.minecraft.entity.monster;
    002
    003    import cpw.mods.fml.common.Side;
    004    import cpw.mods.fml.common.asm.SideOnly;
    005    import net.minecraft.entity.Entity;
    006    import net.minecraft.entity.ai.EntityAIAttackOnCollide;
    007    import net.minecraft.entity.ai.EntityAIAvoidEntity;
    008    import net.minecraft.entity.ai.EntityAICreeperSwell;
    009    import net.minecraft.entity.ai.EntityAIHurtByTarget;
    010    import net.minecraft.entity.ai.EntityAILookIdle;
    011    import net.minecraft.entity.ai.EntityAINearestAttackableTarget;
    012    import net.minecraft.entity.ai.EntityAISwimming;
    013    import net.minecraft.entity.ai.EntityAIWander;
    014    import net.minecraft.entity.ai.EntityAIWatchClosest;
    015    import net.minecraft.entity.effect.EntityLightningBolt;
    016    import net.minecraft.entity.passive.EntityOcelot;
    017    import net.minecraft.entity.player.EntityPlayer;
    018    import net.minecraft.item.Item;
    019    import net.minecraft.nbt.NBTTagCompound;
    020    import net.minecraft.util.DamageSource;
    021    import net.minecraft.world.World;
    022
    023    public class EntityCreeper extends EntityMob
    024    {
    025        /**
    026         * Time when this creeper was last in an active state (Messed up code here, probably causes creeper animation to go
    027         * weird)
    028         */
    029        private int lastActiveTime;
    030
    031        /**
    032         * The amount of time since the creeper was close enough to the player to ignite
    033         */
    034        private int timeSinceIgnited;
    035        private int fuseTime = 30;
    036
    037        /** Explosion radius for this creeper. */
    038        private int explosionRadius = 3;
    039
    040        public EntityCreeper(World par1World)
    041        {
    042            super(par1World);
    043            this.texture = "/mob/creeper.png";
    044            this.tasks.addTask(1, new EntityAISwimming(this));
    045            this.tasks.addTask(2, new EntityAICreeperSwell(this));
    046            this.tasks.addTask(3, new EntityAIAvoidEntity(this, EntityOcelot.class, 6.0F, 0.25F, 0.3F));
    047            this.tasks.addTask(4, new EntityAIAttackOnCollide(this, 0.25F, false));
    048            this.tasks.addTask(5, new EntityAIWander(this, 0.2F));
    049            this.tasks.addTask(6, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F));
    050            this.tasks.addTask(6, new EntityAILookIdle(this));
    051            this.targetTasks.addTask(1, new EntityAINearestAttackableTarget(this, EntityPlayer.class, 16.0F, 0, true));
    052            this.targetTasks.addTask(2, new EntityAIHurtByTarget(this, false));
    053        }
    054
    055        /**
    056         * Returns true if the newer Entity AI code should be run
    057         */
    058        public boolean isAIEnabled()
    059        {
    060            return true;
    061        }
    062
    063        public int func_82143_as()
    064        {
    065            return this.getAttackTarget() == null ? 3 : 3 + (this.health - 1);
    066        }
    067
    068        /**
    069         * Called when the mob is falling. Calculates and applies fall damage.
    070         */
    071        protected void fall(float par1)
    072        {
    073            super.fall(par1);
    074            this.timeSinceIgnited = (int)((float)this.timeSinceIgnited + par1 * 1.5F);
    075
    076            if (this.timeSinceIgnited > this.fuseTime - 5)
    077            {
    078                this.timeSinceIgnited = this.fuseTime - 5;
    079            }
    080        }
    081
    082        public int getMaxHealth()
    083        {
    084            return 20;
    085        }
    086
    087        protected void entityInit()
    088        {
    089            super.entityInit();
    090            this.dataWatcher.addObject(16, Byte.valueOf((byte) - 1));
    091            this.dataWatcher.addObject(17, Byte.valueOf((byte)0));
    092        }
    093
    094        /**
    095         * (abstract) Protected helper method to write subclass entity data to NBT.
    096         */
    097        public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound)
    098        {
    099            super.writeEntityToNBT(par1NBTTagCompound);
    100
    101            if (this.dataWatcher.getWatchableObjectByte(17) == 1)
    102            {
    103                par1NBTTagCompound.setBoolean("powered", true);
    104            }
    105
    106            par1NBTTagCompound.setShort("Fuse", (short)this.fuseTime);
    107            par1NBTTagCompound.setByte("ExplosionRadius", (byte)this.explosionRadius);
    108        }
    109
    110        /**
    111         * (abstract) Protected helper method to read subclass entity data from NBT.
    112         */
    113        public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound)
    114        {
    115            super.readEntityFromNBT(par1NBTTagCompound);
    116            this.dataWatcher.updateObject(17, Byte.valueOf((byte)(par1NBTTagCompound.getBoolean("powered") ? 1 : 0)));
    117
    118            if (par1NBTTagCompound.hasKey("Fuse"))
    119            {
    120                this.fuseTime = par1NBTTagCompound.getShort("Fuse");
    121            }
    122
    123            if (par1NBTTagCompound.hasKey("ExplosionRadius"))
    124            {
    125                this.explosionRadius = par1NBTTagCompound.getByte("ExplosionRadius");
    126            }
    127        }
    128
    129        /**
    130         * Called to update the entity's position/logic.
    131         */
    132        public void onUpdate()
    133        {
    134            if (this.isEntityAlive())
    135            {
    136                this.lastActiveTime = this.timeSinceIgnited;
    137                int var1 = this.getCreeperState();
    138
    139                if (var1 > 0 && this.timeSinceIgnited == 0)
    140                {
    141                    this.func_85030_a("random.fuse", 1.0F, 0.5F);
    142                }
    143
    144                this.timeSinceIgnited += var1;
    145
    146                if (this.timeSinceIgnited < 0)
    147                {
    148                    this.timeSinceIgnited = 0;
    149                }
    150
    151                if (this.timeSinceIgnited >= this.fuseTime)
    152                {
    153                    this.timeSinceIgnited = this.fuseTime;
    154
    155                    if (!this.worldObj.isRemote)
    156                    {
    157                        boolean var2 = this.worldObj.getGameRules().getGameRuleBooleanValue("mobGriefing");
    158
    159                        if (this.getPowered())
    160                        {
    161                            this.worldObj.createExplosion(this, this.posX, this.posY, this.posZ, (float)(this.explosionRadius * 2), var2);
    162                        }
    163                        else
    164                        {
    165                            this.worldObj.createExplosion(this, this.posX, this.posY, this.posZ, (float)this.explosionRadius, var2);
    166                        }
    167
    168                        this.setDead();
    169                    }
    170                }
    171            }
    172
    173            super.onUpdate();
    174        }
    175
    176        /**
    177         * Returns the sound this mob makes when it is hurt.
    178         */
    179        protected String getHurtSound()
    180        {
    181            return "mob.creeper.say";
    182        }
    183
    184        /**
    185         * Returns the sound this mob makes on death.
    186         */
    187        protected String getDeathSound()
    188        {
    189            return "mob.creeper.death";
    190        }
    191
    192        /**
    193         * Called when the mob's health reaches 0.
    194         */
    195        public void onDeath(DamageSource par1DamageSource)
    196        {
    197            super.onDeath(par1DamageSource);
    198
    199            if (par1DamageSource.getEntity() instanceof EntitySkeleton)
    200            {
    201                int var2 = Item.record13.shiftedIndex + this.rand.nextInt(Item.field_85180_cf.shiftedIndex - Item.record13.shiftedIndex + 1);
    202                this.dropItem(var2, 1);
    203            }
    204        }
    205
    206        public boolean attackEntityAsMob(Entity par1Entity)
    207        {
    208            return true;
    209        }
    210
    211        /**
    212         * Returns true if the creeper is powered by a lightning bolt.
    213         */
    214        public boolean getPowered()
    215        {
    216            return this.dataWatcher.getWatchableObjectByte(17) == 1;
    217        }
    218
    219        @SideOnly(Side.CLIENT)
    220
    221        /**
    222         * Params: (Float)Render tick. Returns the intensity of the creeper's flash when it is ignited.
    223         */
    224        public float getCreeperFlashIntensity(float par1)
    225        {
    226            return ((float)this.lastActiveTime + (float)(this.timeSinceIgnited - this.lastActiveTime) * par1) / (float)(this.fuseTime - 2);
    227        }
    228
    229        /**
    230         * Returns the item ID for the item the mob drops on death.
    231         */
    232        protected int getDropItemId()
    233        {
    234            return Item.gunpowder.shiftedIndex;
    235        }
    236
    237        /**
    238         * Returns the current state of creeper, -1 is idle, 1 is 'in fuse'
    239         */
    240        public int getCreeperState()
    241        {
    242            return this.dataWatcher.getWatchableObjectByte(16);
    243        }
    244
    245        /**
    246         * Sets the state of creeper, -1 to idle and 1 to be 'in fuse'
    247         */
    248        public void setCreeperState(int par1)
    249        {
    250            this.dataWatcher.updateObject(16, Byte.valueOf((byte)par1));
    251        }
    252
    253        /**
    254         * Called when a lightning bolt hits the entity.
    255         */
    256        public void onStruckByLightning(EntityLightningBolt par1EntityLightningBolt)
    257        {
    258            super.onStruckByLightning(par1EntityLightningBolt);
    259            this.dataWatcher.updateObject(17, Byte.valueOf((byte)1));
    260        }
    261    }