Jump to content

[SOLVED][1.7.2]Can't stop my entity from fleeing an attack


Recommended Posts

Posted

Hi, I want to make an entity (an elephant) that rears up instead of fleeing when attacked.  I know how to make complex model animations, so the actual rearing isn't hard -- to control it I just need a Boolean to indicate it isRearing and a rearingCounter to progress the animation through the cycle.  So I don't need help with that.

 

I have also set the knockbackResistance attribute to 1.0D so that it doesn't get knocked back.  So I don't need help with that.

 

However, for the life of me I can't get the EntityElephant to stop running away after being hit.  I thought the fleeingTick variable was a clue based on its name and description, however I've overridden places where it is used and frankly after inspecting the vanilla code I don't think it really does much in terms of controlling the actual fleeing. There is only one place in the vanilla code where fleeingTick is even set (to 60) and if I override that and set it to other values it doesn't change the duration of the fleeing, so I'm pretty confident that isn't it (or enough).  It seems that fleeingTick only controls whether the entity will try to attack, but doesn't control the actual duration it runs away.

 

So then I figured that maybe overriding any sprinting would do it, but when the entity runs away it doesn't seem to test isSprinting as true (returns false even while entity is running away) so I guess the fleeing isn't counted as a type of sprint.

 

It does seem that when it is fleeing it is using AIWander for the actual pathfinding and seems that it maybe overrides the movementSpeed attribute somehow.

 

But basically I'm stuck and can't figure it out.  I thought I could simply override the attackEntityFrom() method but it seems I'm missing something.

 

I guess my main question is -- what is the field that controls/indicates that an Entity is fleeing?  It seems to me that there is no such variable but rather it is a wander AI plus a movement modifier.

 

Here is my attackEntityFrom() code, which is just lightly modified code from same method in EntityLivingBase class.  (The fleeingTick = 1 is just my last attempt to control that variable, I tried 0 and also not setting it to anything, plus tried other values like 20 and 120 to see if it affected the length of the flight, but it didn't)

 

    /**
     * Called when the entity is attacked.
     */
    @Override
public boolean attackEntityFrom(DamageSource par1DamageSource, float parDamageAmount)
    {
        if (ForgeHooks.onLivingAttack(this, par1DamageSource, parDamageAmount)) return false;
        if (isEntityInvulnerable())
        {
            return false; // not really "attacked" if invulnerable
        }
        else
        {
            if (worldObj.isRemote) // don't process attack on client side
            {
                return false; 
            }
            else // on server side so process attack
            {
                fleeingTick = 1; // setting to 0 doesn't seem wise, because there is a decrement in super method if statement
                entityToAttack = null;
                resetInLove();;
                setRearing(true); // herd animals will rear when attacked
                entityAge = 0;

                if (getHealth() <= 0.0F) // not really "attacked" if already dead
                {
                    return false;
                }
                else if (par1DamageSource.isFireDamage() && isPotionActive(Potion.fireResistance)) // fire resistance negates fire attack
                {
                    return false;
                }
                else
                {
                    if ((par1DamageSource == DamageSource.anvil || par1DamageSource == DamageSource.fallingBlock) && getEquipmentInSlot(4) != null)
                    {
                        getEquipmentInSlot(4).damageItem((int)(parDamageAmount * 4.0F + rand.nextFloat() * parDamageAmount * 2.0F), this);
                        parDamageAmount *= 0.75F;
                    }

                    limbSwingAmount = 1.5F;
                    boolean flag = true;

                    if (hurtResistantTime > maxHurtResistantTime / 2.0F)
                    {
                        if (parDamageAmount <= lastDamage)
                        {
                            return false;
                        }

                        damageEntity(par1DamageSource, parDamageAmount - lastDamage);
                        lastDamage = parDamageAmount;
                        flag = false;
                    }
                    else
                    {
                        lastDamage = parDamageAmount;
                        prevHealth = getHealth();
                        hurtResistantTime = maxHurtResistantTime;
                        damageEntity(par1DamageSource, parDamageAmount);
                        hurtTime = maxHurtTime = 10;
                    }

                    // process based on what is attacking
                    attackedAtYaw = 0.0F;
                    Entity entity = par1DamageSource.getEntity();

                    if (entity != null)
                    {
                        if (entity instanceof EntityLivingBase) // set revenge on any living entity that attacks
                        {
                            setRevengeTarget((EntityLivingBase)entity);
                        }

                        if (entity instanceof EntityPlayer) // identify attacking player or wolf with kill time determination
                        {
                            recentlyHit = 100;
                            attackingPlayer = (EntityPlayer)entity;
                        }
                        else if (entity instanceof EntityWolf)
                        {
                            EntityWolf entitywolf = (EntityWolf)entity;

                            if (entitywolf.isTamed())
                            {
                                recentlyHit = 100;
                                attackingPlayer = null;
                            }
                        }
                    }

                    if (flag)
                    {
                        worldObj.setEntityState(this, (byte)2);

                        if (par1DamageSource != DamageSource.drown)
                        {
                            setBeenAttacked(); 
                        }

                        if (entity != null)
                        {
                            double d1 = entity.posX - posX;
                            double d0;

                            for (d0 = entity.posZ - posZ; d1 * d1 + d0 * d0 < 1.0E-4D; d0 = (Math.random() - Math.random()) * 0.01D)
                            {
                                d1 = (Math.random() - Math.random()) * 0.01D;
                            }

                            attackedAtYaw = (float)(Math.atan2(d0, d1) * 180.0D / Math.PI) - rotationYaw;
                            knockBack(entity, parDamageAmount, d1, d0); 
                        }
                        else // not an entity that caused damage
                        {
                            attackedAtYaw = (int)(Math.random() * 2.0D) * 180;
                        }
                    }

                    // play sounds for hurt or death
                    String s;

                    if (getHealth() <= 0.0F) // dead
                    {
                        s = getDeathSound();

                        if (flag && s != null)
                        {
                            playSound(s, getSoundVolume(), getSoundPitch());
                        }

                        onDeath(par1DamageSource);
                    }
                    else // hurt
                    {
                        s = getHurtSound();

                        if (flag && s != null)
                        {
                            playSound(s, getSoundVolume(), getSoundPitch());
                        }
                    }

                    return true;
                }
            }        	
        }
    }

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Posted

This may not help a ton, but I've found this in EntityCreature (of which all entities that flee are subclasses):

 

public static final AttributeModifier field_110181_i = (new AttributeModifier(field_110179_h, "Fleeing speed bonus", 2.0D, 2)).setSaved(false);

 

So, maybe if you trace that around, you can find where it's being used. For instance, in EntityAnimal:

 

public boolean attackEntityFrom(DamageSource par1DamageSource, float par2)
{
    if (this.isEntityInvulnerable())
    {
        return false;
    }
    else
    {
        this.fleeingTick = 60;

        if (!this.isAIEnabled())
        {
            IAttributeInstance iattributeinstance = this.getEntityAttribute(SharedMonsterAttributes.movementSpeed);
            if (iattributeinstance.getModifier(field_110179_h) == null)
            {
                iattributeinstance.applyModifier(field_110181_i); //It's being used right here!
            }
        }
   
        this.entityToAttack = null;
        this.inLove = 0;
        return super.attackEntityFrom(par1DamageSource, par2);
    }
}

Posted

This may not help a ton, but I've found this in EntityCreature (of which all entities that flee are subclasses):

 

public static final AttributeModifier field_110181_i = (new AttributeModifier(field_110179_h, "Fleeing speed bonus", 2.0D, 2)).setSaved(false);

 

So, maybe if you trace that around, you can find where it's being used. For instance, in EntityAnimal:

 

public boolean attackEntityFrom(DamageSource par1DamageSource, float par2)
{
    if (this.isEntityInvulnerable())
    {
        return false;
    }
    else
    {
        this.fleeingTick = 60;

        if (!this.isAIEnabled())
        {
            IAttributeInstance iattributeinstance = this.getEntityAttribute(SharedMonsterAttributes.movementSpeed);
            if (iattributeinstance.getModifier(field_110179_h) == null)
            {
                iattributeinstance.applyModifier(field_110181_i); //It's being used right here!
            }
        }
   
        this.entityToAttack = null;
        this.inLove = 0;
        return super.attackEntityFrom(par1DamageSource, par2);
    }
}

 

Thanks.  I actually already found that which is why I said "it is a wander AI plus a movement modifier."

 

In fact if you compare my method code above with that vanilla code you posted, you'd see that I actually already deleted that portion of the code.  Also, the code in vanilla seems to only execute if isAIEnabled() is false, but in my entity it is always true.

 

I've found a lot of little things that are related, but not the actual variable that indicates it is fleeing.  That is why I suspect that instead they are initiating an AIWander at a higher movement speed.

 

The related variables I've found related to timing after an attack does damage are:

  • fleeingTick seems to be a timer to prevent entity from attacking the player for 3 seconds after being hurt
  • hurtResistanceTime seems to be a timer to prevent rapid hits
  • hurtTime seems to be a timer for the red tint effect after entity is hurt
  • recentlyHit seems to be a timer to determine how many drops the entity will give when it dies

 

None of those seem to be used for any logic related to movement speed.

 

I'm thinking that I'm going to poke around in the AIWander.  I'll first try to confirm that it is invoked at that point, and if so, maybe I'll override it and create one where if it is hurt that the AIWander will be canceled.

 

 

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.