Jump to content

Recommended Posts

Posted

Hi everyone,

 

This question may be simple or may be difficult but how would you get a mob to use an item just like the player does?

 

My mob entities have their own inventory and their inventory is full of attack items that use onItemRightClick and onItemUse to attack other entities. My question is how would you get the mob to use these items (call onItemRightClick and call onItemUse etc etc) just like the player does.

 

Any ideas?

Posted

You'll have to implement all of that yourself.

 

Typically, AI is used to simulate the ability of computer-controlled entities to behave as though they were intelligent players, so your best bet is to create some AI tasks that handle the logic for you and then add them to your entities' task lists.

 

This can be very powerful when combined with some custom interfaces, e.g. IEntityItemUser, that allow your AI and Entity classes to interact more effortlessly.

 

Or you can hard-code it all into your entity's onUpdate methods.

 

EDIT: On second thought, I don't think you're going to be able to do it the way you want - all of the item use methods take an EntityPlayer parameter that you obviously won't be able to furnish from your non-player entity, and even if you come up with a way to hack one in there (or pass null), you will either have to restrict the usable items to ones of your own making that don't rely on that parameter, or expect things to go very very wrong.

 

However, if you are okay with passing null, you can make an interface for items that can be used by mobs, such as IMobUsable, and give them methods to call when used by mobs instead of players. Not ideal, but that's the best I can think of.

Posted

Ok I am having some trouble here. I need to implement my own version of onUsingTick so that it can be called only when my entity is using the item. (But when the player uses theitem I need it to continue to use the vanilla onUsing tick) but I am unsure how to do this.

 

in my onLivingUpdate method inside my entity class I am trying to implement all of the player logic that causes a player to use an item so that my custom entity can use the item instead. Basically the following

@Override
 public void onLivingUpdate(){
	super.onLivingUpdate();

        if (this.attackInUse != null)
        {
            ItemStack itemstack = this.getCurrentAttack();

            if (itemstack == this.attackInUse)
            {
            	if (attackInUseCount <= 0)
                {
                    this.onAttackUseFinish();
                }
                else
                {
                	attackInUse.getItem().onUsingTick(attackInUse, this, attackInUseCount);
                      
                    if (--this.attackInUseCount == 0 && !this.worldObj.isRemote)
                    {
                        this.onAttackUseFinish();
                    }
                }
            }
            else
            {
                this.clearAttackInUse();
            }
        }
     

 }

 

I think I did everything correctly so far with a few minor modifications it should work ok but im stuck on the onUsingTick method. I need to be able to have the new onUsingTick available so that I can do

attackInUse.getItem().onUsingTick(attackInUse,(EntityCustom) this, attackInUseCount);

where currently vanilla doesnt allow this since the second parameter needs to be a EntityPlayer.

 

 

 

    public ItemStack[] attacks = new ItemStack[4];
    public int currentAttack;
    private ItemStack attackInUse;
    private int attackInUseCount;

  public ItemStack getCurrentAttack()
    {
        return this.currentAttack < 4 && this.currentAttack >= 0 ? this.attacks[this.currentAttack] : null;
    }
  
  public void setAttackItemInUse(ItemStack itemStack, int maxItemUseDuration)
    {
        if (itemStack != this.attackInUse)
        {
            if (maxItemUseDuration <= 0) return;
            this.attackInUse = itemStack;
            this.attackInUseCount = maxItemUseDuration;

            if (!this.worldObj.isRemote)
            {
                this.setEating(true);
            }
        }
    }
  
  public void clearAttackInUse()
    {
        this.attackInUse = null;
        this.attackInUseCount = 0;

        if (!this.worldObj.isRemote)
        {
            this.setEating(false);
        }
    }
  
  protected void onAttackUseFinish()
    {
        if (this.attackInUse != null)
        {
            int i = this.attackInUse.stackSize;
            /**may cause problems*/
            ItemStack itemstack = this.attackInUse.onFoodEaten(this.worldObj, null);

           if (itemstack != this.attackInUse || itemstack != null && itemstack.stackSize != i)
            {
            	this.attacks[this.currentAttack] = itemstack;

                if (itemstack != null && itemstack.stackSize == 0)
                {
                    this.attacks[this.currentAttack] = null;
                }
            }

            this.clearAttackInUse();
        }
    }
  
  
  
@Override
 public void onLivingUpdate(){
	super.onLivingUpdate();

        if (this.attackInUse != null)
        {
            ItemStack itemstack = this.getCurrentAttack();

            if (itemstack == this.attackInUse)
            {
            	if (attackInUseCount <= 0)
                {
                    this.onAttackUseFinish();
                }
                else
                {
                	attackInUse.getItem().onUsingTick(attackInUse, this, attackInUseCount);
                      
                    if (--this.attackInUseCount == 0 && !this.worldObj.isRemote)
                    {
                        this.onAttackUseFinish();
                    }
                }
            }
            else
            {
                this.clearAttackInUse();
            }
        }
       

 }
   

 

 

 

I have a CustomItem class which extends the vanilla Item class. My CustomItem class is then extended by my attack item class. The attack items are the items that I want my entity to be able to use. But in order for this to work I need to be able to have the entity call the onItemRightClick and onItemUse methods. Inside this class is where I put my custom onUsingTick that I need to be able to call to set my item in use, but I am unsure how to do that.

 

 

public class CustomItem extends Item {

public CustomItem() {
	super();
	setMaxStackSize(64);


}

  /**
     * Called each tick while using an item.
     * @param stack The Item being used
     * @param player The Entity using the item
     * @param count The amount of time in tick the item has been used for continuously
     */
    public void onUsingTick(ItemStack stack, EntityCustom customEntity, int count)
    {
    }
       

@SideOnly(Side.CLIENT)
public void registerIcons(IIconRegister iconRegister) {
	this.itemIcon = iconRegister.registerIcon(CustomMod.modid + ":"
			+ this.getUnlocalizedName().substring(5));
}

}

 

 

Im not sure how to implement the onUsingTick method that is in my generic CustomItem class rather than the one that is inside the vanilla Item class. I cant use the vanilla one since it requires the player as a parameter and obviously I cannot make my custom mob a player entity.

 

Basically to make my item useable by both the player and the entity I am trying to implement a second onItemRightClick method that replaces the player parameter with the custom entity parameter so that it can be called by my entity from its AI

 

 

public ItemStack onItemRightClick(ItemStack itemStack, World world,	EntityCustom customEntity) {

	                       int fatigueMultiplier = 1;

				if(ball == true && (getCooldown(itemStack) == 0)){
				  fatigueMultiplier = 2;

				   EntityRangedAttackBase distanceAttack = new EntityRangedAttack(world, customEntity).setType(attackType).setArea(damageRadius);
      				           distanceAttack.setBaseDamageForProjectileAttack(baseDmg);
      			             	    setCooldown(itemStack, 30);

      				               if (!world.isRemote) {
      					      WorldHelper.playSoundAtEntity(customEntity,BattleSoundsList.WHOOSH, 0.4F, 0.5F);
      					       world.spawnEntityInWorld(distanceAttack);
      				               }

      				
		              } else if(ball ==false){
					customEntity.setAttackItemInUse(itemStack,getMaxItemUseDuration(itemStack));
			           }


	return itemStack;
}

 

 

 

Any ideas how to implement the onUsingTick method from inside my customItem class rather than the regular vanilla onUsingTick method?? Or any ideas on how to implement what I am trying to achieve in a simpler way??

Posted

Nvm Im stupid

                        if(attackInUse.getItem() instanceof CustomItem){
                		CustomItem attack = (CustomItem ) attackInUse.getItem();
                		attack.onUsingTick(attackInUse, this, attackInUseCount);
                	}

Posted

I strongly suggest you use an interface for your additional item methods instead of a 'base' class - it will be far more flexible, both for you and for anyone that may write addons for your mod.

 

Just as a simple example, you have your CustomItem class that extends Item and adds one or more methods for interacting with the mob item in use. All fine and dandy. BUT, now imagine you have a custom sword that, logically, extends ItemSword, but you want your mobs to be able to use it, too... now what? You are stuck.

 

Java does not support multiple inheritance, so you cannot extend both ItemSword and CustomItem at the same time, and you have to either add an additional check in your item use logic to account for the sword exception, OR you have to duplicate all of the ItemSword code in a new class that extends CustomItem, and even then that custom sword that isn't a sword will not play well with some other mods that check for instances of ItemSword in their logic.

 

The solution is interfaces:

public interface IMobUsable {
    void onUsingTick(ItemStack stack, EntityLivingBase (or EntityCustom) entity, int useCount);
}

Now ANY item can implement this interface and be usable by your mobs, even items from other mods if the author wants to make their item(s) compatible with your mobs.

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.

×
×
  • Create New...

Important Information

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