    001    package net.minecraft.entity.boss;
    002
    003    import cpw.mods.fml.relauncher.Side;
    004    import cpw.mods.fml.relauncher.SideOnly;
    005    import java.util.List;
    006    import net.minecraft.block.Block;
    007    import net.minecraft.command.IEntitySelector;
    008    import net.minecraft.entity.Entity;
    009    import net.minecraft.entity.EntityLiving;
    010    import net.minecraft.entity.EnumCreatureAttribute;
    011    import net.minecraft.entity.IRangedAttackMob;
    012    import net.minecraft.entity.ai.EntityAIArrowAttack;
    013    import net.minecraft.entity.ai.EntityAIHurtByTarget;
    014    import net.minecraft.entity.ai.EntityAILookIdle;
    015    import net.minecraft.entity.ai.EntityAINearestAttackableTarget;
    016    import net.minecraft.entity.ai.EntityAISwimming;
    017    import net.minecraft.entity.ai.EntityAIWander;
    018    import net.minecraft.entity.ai.EntityAIWatchClosest;
    019    import net.minecraft.entity.monster.EntityMob;
    020    import net.minecraft.entity.player.EntityPlayer;
    021    import net.minecraft.entity.projectile.EntityArrow;
    022    import net.minecraft.entity.projectile.EntityWitherSkull;
    023    import net.minecraft.item.Item;
    024    import net.minecraft.nbt.NBTTagCompound;
    025    import net.minecraft.potion.PotionEffect;
    026    import net.minecraft.util.DamageSource;
    027    import net.minecraft.util.MathHelper;
    028    import net.minecraft.world.World;
    029
    030    public class EntityWither extends EntityMob implements IBossDisplayData, IRangedAttackMob
    031    {
    032        private float[] field_82220_d = new float[2];
    033        private float[] field_82221_e = new float[2];
    034        private float[] field_82217_f = new float[2];
    035        private float[] field_82218_g = new float[2];
    036        private int[] field_82223_h = new int[2];
    037        private int[] field_82224_i = new int[2];
    038        private int field_82222_j;
    039
    040        /** Selector used to determine the entities a wither boss should attack. */
    041        private static final IEntitySelector attackEntitySelector = new EntityWitherAttackFilter();
    042
    043        public EntityWither(World par1World)
    044        {
    045            super(par1World);
    046            this.setEntityHealth(this.getMaxHealth());
    047            this.texture = "/mob/wither.png";
    048            this.setSize(0.9F, 4.0F);
    049            this.isImmuneToFire = true;
    050            this.moveSpeed = 0.6F;
    051            this.getNavigator().setCanSwim(true);
    052            this.tasks.addTask(0, new EntityAISwimming(this));
    053            this.tasks.addTask(2, new EntityAIArrowAttack(this, this.moveSpeed, 40, 20.0F));
    054            this.tasks.addTask(5, new EntityAIWander(this, this.moveSpeed));
    055            this.tasks.addTask(6, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F));
    056            this.tasks.addTask(7, new EntityAILookIdle(this));
    057            this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, false));
    058            this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, EntityLiving.class, 30.0F, 0, false, false, attackEntitySelector));
    059            this.experienceValue = 50;
    060        }
    061
    062        protected void entityInit()
    063        {
    064            super.entityInit();
    065            this.dataWatcher.addObject(16, new Integer(100));
    066            this.dataWatcher.addObject(17, new Integer(0));
    067            this.dataWatcher.addObject(18, new Integer(0));
    068            this.dataWatcher.addObject(19, new Integer(0));
    069            this.dataWatcher.addObject(20, new Integer(0));
    070        }
    071
    072        /**
    073         * (abstract) Protected helper method to write subclass entity data to NBT.
    074         */
    075        public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound)
    076        {
    077            super.writeEntityToNBT(par1NBTTagCompound);
    078            par1NBTTagCompound.setInteger("Invul", this.func_82212_n());
    079        }
    080
    081        /**
    082         * (abstract) Protected helper method to read subclass entity data from NBT.
    083         */
    084        public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound)
    085        {
    086            super.readEntityFromNBT(par1NBTTagCompound);
    087            this.func_82215_s(par1NBTTagCompound.getInteger("Invul"));
    088            this.dataWatcher.updateObject(16, Integer.valueOf(this.health));
    089        }
    090
    091        @SideOnly(Side.CLIENT)
    092        public float getShadowSize()
    093        {
    094            return this.height / 8.0F;
    095        }
    096
    097        /**
    098         * Returns the sound this mob makes while it's alive.
    099         */
    100        protected String getLivingSound()
    101        {
    102            return "mob.wither.idle";
    103        }
    104
    105        /**
    106         * Returns the sound this mob makes when it is hurt.
    107         */
    108        protected String getHurtSound()
    109        {
    110            return "mob.wither.hurt";
    111        }
    112
    113        /**
    114         * Returns the sound this mob makes on death.
    115         */
    116        protected String getDeathSound()
    117        {
    118            return "mob.wither.death";
    119        }
    120
    121        @SideOnly(Side.CLIENT)
    122
    123        /**
    124         * Returns the texture's file path as a String.
    125         */
    126        public String getTexture()
    127        {
    128            int var1 = this.func_82212_n();
    129            return var1 > 0 && (var1 > 80 || var1 / 5 % 2 != 1) ? "/mob/wither_invul.png" : "/mob/wither.png";
    130        }
    131
    132        /**
    133         * Called frequently so the entity can update its state every tick as required. For example, zombies and skeletons
    134         * use this to react to sunlight and start to burn.
    135         */
    136        public void onLivingUpdate()
    137        {
    138            if (!this.worldObj.isRemote)
    139            {
    140                this.dataWatcher.updateObject(16, Integer.valueOf(this.health));
    141            }
    142
    143            this.motionY *= 0.6000000238418579D;
    144            double var4;
    145            double var6;
    146            double var8;
    147
    148            if (!this.worldObj.isRemote && this.getWatchedTargetId(0) > 0)
    149            {
    150                Entity var1 = this.worldObj.getEntityByID(this.getWatchedTargetId(0));
    151
    152                if (var1 != null)
    153                {
    154                    if (this.posY < var1.posY || !this.isArmored() && this.posY < var1.posY + 5.0D)
    155                    {
    156                        if (this.motionY < 0.0D)
    157                        {
    158                            this.motionY = 0.0D;
    159                        }
    160
    161                        this.motionY += (0.5D - this.motionY) * 0.6000000238418579D;
    162                    }
    163
    164                    double var2 = var1.posX - this.posX;
    165                    var4 = var1.posZ - this.posZ;
    166                    var6 = var2 * var2 + var4 * var4;
    167
    168                    if (var6 > 9.0D)
    169                    {
    170                        var8 = (double)MathHelper.sqrt_double(var6);
    171                        this.motionX += (var2 / var8 * 0.5D - this.motionX) * 0.6000000238418579D;
    172                        this.motionZ += (var4 / var8 * 0.5D - this.motionZ) * 0.6000000238418579D;
    173                    }
    174                }
    175            }
    176
    177            if (this.motionX * this.motionX + this.motionZ * this.motionZ > 0.05000000074505806D)
    178            {
    179                this.rotationYaw = (float)Math.atan2(this.motionZ, this.motionX) * (180F / (float)Math.PI) - 90.0F;
    180            }
    181
    182            super.onLivingUpdate();
    183            int var20;
    184
    185            for (var20 = 0; var20 < 2; ++var20)
    186            {
    187                this.field_82218_g[var20] = this.field_82221_e[var20];
    188                this.field_82217_f[var20] = this.field_82220_d[var20];
    189            }
    190
    191            int var21;
    192
    193            for (var20 = 0; var20 < 2; ++var20)
    194            {
    195                var21 = this.getWatchedTargetId(var20 + 1);
    196                Entity var3 = null;
    197
    198                if (var21 > 0)
    199                {
    200                    var3 = this.worldObj.getEntityByID(var21);
    201                }
    202
    203                if (var3 != null)
    204                {
    205                    var4 = this.func_82214_u(var20 + 1);
    206                    var6 = this.func_82208_v(var20 + 1);
    207                    var8 = this.func_82213_w(var20 + 1);
    208                    double var10 = var3.posX - var4;
    209                    double var12 = var3.posY + (double)var3.getEyeHeight() - var6;
    210                    double var14 = var3.posZ - var8;
    211                    double var16 = (double)MathHelper.sqrt_double(var10 * var10 + var14 * var14);
    212                    float var18 = (float)(Math.atan2(var14, var10) * 180.0D / Math.PI) - 90.0F;
    213                    float var19 = (float)(-(Math.atan2(var12, var16) * 180.0D / Math.PI));
    214                    this.field_82220_d[var20] = this.func_82204_b(this.field_82220_d[var20], var19, 40.0F);
    215                    this.field_82221_e[var20] = this.func_82204_b(this.field_82221_e[var20], var18, 10.0F);
    216                }
    217                else
    218                {
    219                    this.field_82221_e[var20] = this.func_82204_b(this.field_82221_e[var20], this.renderYawOffset, 10.0F);
    220                }
    221            }
    222
    223            boolean var22 = this.isArmored();
    224
    225            for (var21 = 0; var21 < 3; ++var21)
    226            {
    227                double var23 = this.func_82214_u(var21);
    228                double var5 = this.func_82208_v(var21);
    229                double var7 = this.func_82213_w(var21);
    230                this.worldObj.spawnParticle("smoke", var23 + this.rand.nextGaussian() * 0.30000001192092896D, var5 + this.rand.nextGaussian() * 0.30000001192092896D, var7 + this.rand.nextGaussian() * 0.30000001192092896D, 0.0D, 0.0D, 0.0D);
    231
    232                if (var22 && this.worldObj.rand.nextInt(4) == 0)
    233                {
    234                    this.worldObj.spawnParticle("mobSpell", var23 + this.rand.nextGaussian() * 0.30000001192092896D, var5 + this.rand.nextGaussian() * 0.30000001192092896D, var7 + this.rand.nextGaussian() * 0.30000001192092896D, 0.699999988079071D, 0.699999988079071D, 0.5D);
    235                }
    236            }
    237
    238            if (this.func_82212_n() > 0)
    239            {
    240                for (var21 = 0; var21 < 3; ++var21)
    241                {
    242                    this.worldObj.spawnParticle("mobSpell", this.posX + this.rand.nextGaussian() * 1.0D, this.posY + (double)(this.rand.nextFloat() * 3.3F), this.posZ + this.rand.nextGaussian() * 1.0D, 0.699999988079071D, 0.699999988079071D, 0.8999999761581421D);
    243                }
    244            }
    245        }
    246
    247        protected void updateAITasks()
    248        {
    249            int var1;
    250
    251            if (this.func_82212_n() > 0)
    252            {
    253                var1 = this.func_82212_n() - 1;
    254
    255                if (var1 <= 0)
    256                {
    257                    this.worldObj.newExplosion(this, this.posX, this.posY + (double)this.getEyeHeight(), this.posZ, 7.0F, false, this.worldObj.getGameRules().getGameRuleBooleanValue("mobGriefing"));
    258                    this.worldObj.func_82739_e(1013, (int)this.posX, (int)this.posY, (int)this.posZ, 0);
    259                }
    260
    261                this.func_82215_s(var1);
    262
    263                if (this.ticksExisted % 10 == 0)
    264                {
    265                    this.heal(10);
    266                }
    267            }
    268            else
    269            {
    270                super.updateAITasks();
    271                int var13;
    272
    273                for (var1 = 1; var1 < 3; ++var1)
    274                {
    275                    if (this.ticksExisted >= this.field_82223_h[var1 - 1])
    276                    {
    277                        this.field_82223_h[var1 - 1] = this.ticksExisted + 10 + this.rand.nextInt(10);
    278
    279                        if (this.worldObj.difficultySetting >= 2)
    280                        {
    281                            int var10001 = var1 - 1;
    282                            int var10003 = this.field_82224_i[var1 - 1];
    283                            this.field_82224_i[var10001] = this.field_82224_i[var1 - 1] + 1;
    284
    285                            if (var10003 > 15)
    286                            {
    287                                float var2 = 10.0F;
    288                                float var3 = 5.0F;
    289                                double var4 = MathHelper.getRandomDoubleInRange(this.rand, this.posX - (double)var2, this.posX + (double)var2);
    290                                double var6 = MathHelper.getRandomDoubleInRange(this.rand, this.posY - (double)var3, this.posY + (double)var3);
    291                                double var8 = MathHelper.getRandomDoubleInRange(this.rand, this.posZ - (double)var2, this.posZ + (double)var2);
    292                                this.func_82209_a(var1 + 1, var4, var6, var8, true);
    293                                this.field_82224_i[var1 - 1] = 0;
    294                            }
    295                        }
    296
    297                        var13 = this.getWatchedTargetId(var1);
    298
    299                        if (var13 > 0)
    300                        {
    301                            Entity var15 = this.worldObj.getEntityByID(var13);
    302
    303                            if (var15 != null && var15.isEntityAlive() && this.getDistanceSqToEntity(var15) <= 900.0D && this.canEntityBeSeen(var15))
    304                            {
    305                                this.func_82216_a(var1 + 1, (EntityLiving)var15);
    306                                this.field_82223_h[var1 - 1] = this.ticksExisted + 40 + this.rand.nextInt(20);
    307                                this.field_82224_i[var1 - 1] = 0;
    308                            }
    309                            else
    310                            {
    311                                this.func_82211_c(var1, 0);
    312                            }
    313                        }
    314                        else
    315                        {
    316                            List var14 = this.worldObj.selectEntitiesWithinAABB(EntityLiving.class, this.boundingBox.expand(20.0D, 8.0D, 20.0D), attackEntitySelector);
    317
    318                            for (int var17 = 0; var17 < 10 && !var14.isEmpty(); ++var17)
    319                            {
    320                                EntityLiving var5 = (EntityLiving)var14.get(this.rand.nextInt(var14.size()));
    321
    322                                if (var5 != this && var5.isEntityAlive() && this.canEntityBeSeen(var5))
    323                                {
    324                                    if (var5 instanceof EntityPlayer)
    325                                    {
    326                                        if (!((EntityPlayer)var5).capabilities.disableDamage)
    327                                        {
    328                                            this.func_82211_c(var1, var5.entityId);
    329                                        }
    330                                    }
    331                                    else
    332                                    {
    333                                        this.func_82211_c(var1, var5.entityId);
    334                                    }
    335
    336                                    break;
    337                                }
    338
    339                                var14.remove(var5);
    340                            }
    341                        }
    342                    }
    343                }
    344
    345                if (this.getAttackTarget() != null)
    346                {
    347                    this.func_82211_c(0, this.getAttackTarget().entityId);
    348                }
    349                else
    350                {
    351                    this.func_82211_c(0, 0);
    352                }
    353
    354                if (this.field_82222_j > 0)
    355                {
    356                    --this.field_82222_j;
    357
    358                    if (this.field_82222_j == 0 && this.worldObj.getGameRules().getGameRuleBooleanValue("mobGriefing"))
    359                    {
    360                        var1 = MathHelper.floor_double(this.posY);
    361                        var13 = MathHelper.floor_double(this.posX);
    362                        int var16 = MathHelper.floor_double(this.posZ);
    363                        boolean var19 = false;
    364
    365                        for (int var18 = -1; var18 <= 1; ++var18)
    366                        {
    367                            for (int var20 = -1; var20 <= 1; ++var20)
    368                            {
    369                                for (int var7 = 0; var7 <= 3; ++var7)
    370                                {
    371                                    int var21 = var13 + var18;
    372                                    int var9 = var1 + var7;
    373                                    int var10 = var16 + var20;
    374                                    int var11 = this.worldObj.getBlockId(var21, var9, var10);
    375
    376                                    if (var11 > 0 && var11 != Block.bedrock.blockID && var11 != Block.endPortal.blockID && var11 != Block.endPortalFrame.blockID)
    377                                    {
    378                                        int var12 = this.worldObj.getBlockMetadata(var21, var9, var10);
    379                                        this.worldObj.playAuxSFX(2001, var21, var9, var10, var11 + (var12 << 12));
    380                                        Block.blocksList[var11].dropBlockAsItem(this.worldObj, var21, var9, var10, var12, 0);
    381                                        this.worldObj.setBlockWithNotify(var21, var9, var10, 0);
    382                                        var19 = true;
    383                                    }
    384                                }
    385                            }
    386                        }
    387
    388                        if (var19)
    389                        {
    390                            this.worldObj.playAuxSFXAtEntity((EntityPlayer)null, 1012, (int)this.posX, (int)this.posY, (int)this.posZ, 0);
    391                        }
    392                    }
    393                }
    394
    395                if (this.ticksExisted % 20 == 0)
    396                {
    397                    this.heal(1);
    398                }
    399            }
    400        }
    401
    402        public void func_82206_m()
    403        {
    404            this.func_82215_s(220);
    405            this.setEntityHealth(this.getMaxHealth() / 3);
    406        }
    407
    408        /**
    409         * Sets the Entity inside a web block.
    410         */
    411        public void setInWeb() {}
    412
    413        /**
    414         * Returns the current armor value as determined by a call to InventoryPlayer.getTotalArmorValue
    415         */
    416        public int getTotalArmorValue()
    417        {
    418            return 4;
    419        }
    420
    421        private double func_82214_u(int par1)
    422        {
    423            if (par1 <= 0)
    424            {
    425                return this.posX;
    426            }
    427            else
    428            {
    429                float var2 = (this.renderYawOffset + (float)(180 * (par1 - 1))) / 180.0F * (float)Math.PI;
    430                float var3 = MathHelper.cos(var2);
    431                return this.posX + (double)var3 * 1.3D;
    432            }
    433        }
    434
    435        private double func_82208_v(int par1)
    436        {
    437            return par1 <= 0 ? this.posY + 3.0D : this.posY + 2.2D;
    438        }
    439
    440        private double func_82213_w(int par1)
    441        {
    442            if (par1 <= 0)
    443            {
    444                return this.posZ;
    445            }
    446            else
    447            {
    448                float var2 = (this.renderYawOffset + (float)(180 * (par1 - 1))) / 180.0F * (float)Math.PI;
    449                float var3 = MathHelper.sin(var2);
    450                return this.posZ + (double)var3 * 1.3D;
    451            }
    452        }
    453
    454        private float func_82204_b(float par1, float par2, float par3)
    455        {
    456            float var4 = MathHelper.wrapAngleTo180_float(par2 - par1);
    457
    458            if (var4 > par3)
    459            {
    460                var4 = par3;
    461            }
    462
    463            if (var4 < -par3)
    464            {
    465                var4 = -par3;
    466            }
    467
    468            return par1 + var4;
    469        }
    470
    471        private void func_82216_a(int par1, EntityLiving par2EntityLiving)
    472        {
    473            this.func_82209_a(par1, par2EntityLiving.posX, par2EntityLiving.posY + (double)par2EntityLiving.getEyeHeight() * 0.5D, par2EntityLiving.posZ, par1 == 0 && this.rand.nextFloat() < 0.001F);
    474        }
    475
    476        private void func_82209_a(int par1, double par2, double par4, double par6, boolean par8)
    477        {
    478            this.worldObj.playAuxSFXAtEntity((EntityPlayer)null, 1014, (int)this.posX, (int)this.posY, (int)this.posZ, 0);
    479            double var9 = this.func_82214_u(par1);
    480            double var11 = this.func_82208_v(par1);
    481            double var13 = this.func_82213_w(par1);
    482            double var15 = par2 - var9;
    483            double var17 = par4 - var11;
    484            double var19 = par6 - var13;
    485            EntityWitherSkull var21 = new EntityWitherSkull(this.worldObj, this, var15, var17, var19);
    486
    487            if (par8)
    488            {
    489                var21.setInvulnerable(true);
    490            }
    491
    492            var21.posY = var11;
    493            var21.posX = var9;
    494            var21.posZ = var13;
    495            this.worldObj.spawnEntityInWorld(var21);
    496        }
    497
    498        /**
    499         * Attack the specified entity using a ranged attack.
    500         */
    501        public void attackEntityWithRangedAttack(EntityLiving par1EntityLiving)
    502        {
    503            this.func_82216_a(0, par1EntityLiving);
    504        }
    505
    506        /**
    507         * Called when the entity is attacked.
    508         */
    509        public boolean attackEntityFrom(DamageSource par1DamageSource, int par2)
    510        {
    511            if (this.func_85032_ar())
    512            {
    513                return false;
    514            }
    515            else if (par1DamageSource == DamageSource.drown)
    516            {
    517                return false;
    518            }
    519            else if (this.func_82212_n() > 0)
    520            {
    521                return false;
    522            }
    523            else
    524            {
    525                Entity var3;
    526
    527                if (this.isArmored())
    528                {
    529                    var3 = par1DamageSource.getSourceOfDamage();
    530
    531                    if (var3 instanceof EntityArrow)
    532                    {
    533                        return false;
    534                    }
    535                }
    536
    537                var3 = par1DamageSource.getEntity();
    538
    539                if (var3 != null && !(var3 instanceof EntityPlayer) && var3 instanceof EntityLiving && ((EntityLiving)var3).getCreatureAttribute() == this.getCreatureAttribute())
    540                {
    541                    return false;
    542                }
    543                else
    544                {
    545                    if (this.field_82222_j <= 0)
    546                    {
    547                        this.field_82222_j = 20;
    548                    }
    549
    550                    for (int var4 = 0; var4 < this.field_82224_i.length; ++var4)
    551                    {
    552                        this.field_82224_i[var4] += 3;
    553                    }
    554
    555                    return super.attackEntityFrom(par1DamageSource, par2);
    556                }
    557            }
    558        }
    559
    560        /**
    561         * Drop 0-2 items of this living's type
    562         */
    563        protected void dropFewItems(boolean par1, int par2)
    564        {
    565            this.dropItem(Item.netherStar.shiftedIndex, 1);
    566        }
    567
    568        /**
    569         * Makes the entity despawn if requirements are reached
    570         */
    571        protected void despawnEntity()
    572        {
    573            this.entityAge = 0;
    574        }
    575
    576        @SideOnly(Side.CLIENT)
    577        public int getBrightnessForRender(float par1)
    578        {
    579            return 15728880;
    580        }
    581
    582        /**
    583         * Returns true if other Entities should be prevented from moving through this Entity.
    584         */
    585        public boolean canBeCollidedWith()
    586        {
    587            return !this.isDead;
    588        }
    589
    590        /**
    591         * Returns the health points of the dragon.
    592         */
    593        public int getDragonHealth()
    594        {
    595            return this.dataWatcher.getWatchableObjectInt(16);
    596        }
    597
    598        /**
    599         * Called when the mob is falling. Calculates and applies fall damage.
    600         */
    601        protected void fall(float par1) {}
    602
    603        /**
    604         * adds a PotionEffect to the entity
    605         */
    606        public void addPotionEffect(PotionEffect par1PotionEffect) {}
    607
    608        /**
    609         * Returns true if the newer Entity AI code should be run
    610         */
    611        protected boolean isAIEnabled()
    612        {
    613            return true;
    614        }
    615
    616        public int getMaxHealth()
    617        {
    618            return 300;
    619        }
    620
    621        @SideOnly(Side.CLIENT)
    622        public float func_82207_a(int par1)
    623        {
    624            return this.field_82221_e[par1];
    625        }
    626
    627        @SideOnly(Side.CLIENT)
    628        public float func_82210_r(int par1)
    629        {
    630            return this.field_82220_d[par1];
    631        }
    632
    633        public int func_82212_n()
    634        {
    635            return this.dataWatcher.getWatchableObjectInt(20);
    636        }
    637
    638        public void func_82215_s(int par1)
    639        {
    640            this.dataWatcher.updateObject(20, Integer.valueOf(par1));
    641        }
    642
    643        /**
    644         * Returns the target entity ID if present, or -1 if not @param par1 The target offset, should be from 0-2
    645         */
    646        public int getWatchedTargetId(int par1)
    647        {
    648            return this.dataWatcher.getWatchableObjectInt(17 + par1);
    649        }
    650
    651        public void func_82211_c(int par1, int par2)
    652        {
    653            this.dataWatcher.updateObject(17 + par1, Integer.valueOf(par2));
    654        }
    655
    656        /**
    657         * Returns whether the wither is armored with its boss armor or not by checking whether its health is below half of
    658         * its maximum.
    659         */
    660        public boolean isArmored()
    661        {
    662            return this.getDragonHealth() <= this.getMaxHealth() / 2;
    663        }
    664
    665        /**
    666         * Get this Entity's EnumCreatureAttribute
    667         */
    668        public EnumCreatureAttribute getCreatureAttribute()
    669        {
    670            return EnumCreatureAttribute.UNDEAD;
    671        }
    672    }