Jump to content

[1.7.10] Multipart Mob Issues


ChaKha

Recommended Posts

Hello,

 

I've been making a few posts recently on the forums about small, random problems that have to do with a multipart mob I'm attempting to create. However, I've run into so many issues making it that I think my problem is that I don't fully understand how to make a multipart entity. I'm already fully aware of how to completely make a single entity (thanks to some Jabelar tutorials :P). So, here's what I'm hoping someone can provide: Is there any sort of tutorial or guidance on making a multipart entity besides studying the enderdragon code (as I've already done that)? I apologize if I'm simply missing some obvious facts, but I need help.

 

Thanks for reading at least!

Link to comment
Share on other sites

It is better to post or at least explain what you've tried when you're asking for help.

 

But here is some advice.

 

First off, the models for an entity are already multi-part (like it has head and body and legs and arms). So when someone asks about making a multi-part entity, what they mean is that they want a complex hitbox. Because as you probably know, the hitboxes for a single entity are quite limited. The hitbox for a single entity must be a rectangular box and the X and Z dimensions have to be the same and the hitbox size is limited by pathfinding algorithms. So I'll assume that what you want to do is have a complex multi-part hitbox for your entity.

 

Anyway, the way I would do it is actually make the "entity" made up of multiple actual entities. One part (like the body) could be considered the parent entity and could have the full entity model, and the rest of the entities would be invisible and will follow along. This means that whenever you construct the parent entity part, it will additionally create the other parts (in the correct relative positions). To create the parent/child relationship between the entities, you'll need a list in the parent entity that keeps track of the instances of the child entities, and each child entity should have a field that contains the parent entity. Then you'll have information in each part about the other parts, which you'll need for your logic of movement and damage.

 

Then, all you need to do is:

1) move everything together. You'd do this by moving the parent entity part and the onUpdate() method for that entity should also automatically update the other parts' positions (and maybe rotations).

2) decide how you want to handle damage. You might just want to have the damage in the parent entity reduced when any child entity is hit. Or depending on the mob, maybe you want each part to get damaged separately. In the first case, you'll have to handle the case when the child parts are hit and instead inflict the damage on the associated parent.

3) if parent part dies, make sure to kill of the child parts.

 

The only other tricky thing is pathfinding. There is a reason that the Ender Dragon is flying and also destroys blocks -- if it did not then the path finding would be very difficult -- imagine a complex entity trying to move around in a cave or forest. To make multi-part entity work with pathfinding is a tough coding challenge, so it is best if you can "cheat" -- like maybe allow it to move anywhere the parent part can go -- i.e. only do pathfinding on the parent part and don't worry if the rest of the parts overlap into blocks.

 

That's pretty much it! Hope it helps.

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

Link to comment
Share on other sites

It is better to post or at least explain what you've tried when you're asking for help.

Alright. So, all I have really tried so far is copy/editing code from the enderdragon and some other mods that included complex hitbox entities. If you want to see exactly what I've done, then here's the very incomplete entity class:

public class EntityNWPlantBossTendril extends EntityLiving implements IEntityMultiPart {

public double targetX;
    public double targetY;
    public double targetZ;
    private static int MAX_HEALTH = 50;
    private static float ARMOR_MULTIPLIER = 2F;
public Entity[] partArray;
public EntityDragonPart tendrilBase;
public EntityDragonPart tendrilPart1;
public EntityDragonPart tendrilPart2;
public EntityDragonPart tendrilPart3;
public EntityDragonPart tendrilPart4;
public EntityDragonPart tendrilPart5;
public EntityDragonPart tendrilPart6;
public EntityDragonPart tendrilPart7;
public EntityDragonPart tendrilPart8;
public EntityDragonPart tendrilPart9;
public EntityDragonPart tendrilPart10;
public EntityDragonPart tendrilPart11;
public EntityDragonPart tendrilPart12;
public EntityDragonPart tendrilPart13;
public EntityDragonPart tendrilPart14;
    public EntityNWPlantBoss master;

public EntityNWPlantBossTendril(World world) {
	super(world);
	partArray = (new Entity[] {
			tendrilBase = new EntityDragonPart(this, "base", 4F, 4F), tendrilPart1 = new EntityDragonPart(this, "tendrilPart1", 10.0F, 10.0F), tendrilPart2 = new EntityDragonPart(this, "tendrilPart2", 10.0F, 10.0F), tendrilPart3 = new EntityDragonPart(this, "tendrilPart3", 10.0F, 10.0F), tendrilPart4 = new EntityDragonPart(this, "tendrilPart4", 10.0F, 10.0F), tendrilPart5 = new EntityDragonPart(this, "tendrilPart5", 10.0F, 10.0F), tendrilPart6 = new EntityDragonPart(this, "tendrilPart6", 10.0F, 10.0F), tendrilPart7 = new EntityDragonPart(this, "tendrilPart7", 10.0F, 10.0F), tendrilPart8 = new EntityDragonPart(this, "tendrilPart8", 10.0F, 10.0F), tendrilPart9 = new EntityDragonPart(this, "tendrilPart9", 10.0F, 10.0F), tendrilPart10 = new EntityDragonPart(this, "tendrilPart10", 10.0F, 10.0F), tendrilPart11 = new EntityDragonPart(this, "tendrilPart11", 10.0F, 10.0F), tendrilPart12 = new EntityDragonPart(this, "tendrilPart12", 10.0F, 10.0F), tendrilPart13 = new EntityDragonPart(this, "tendrilPart13", 10.0F, 10.0F), tendrilPart14 = new EntityDragonPart(this, "tendrilPart14", 10.0F, 10.0F)
	});
	setSize(2.125F, 15.0F);
	ignoreFrustumCheck = true;
	experienceValue = 20;//WIP
}

public EntityNWPlantBossTendril(World world, double x, double y, double z) {
        this(world);
        setPosition(x, y, z);
    }

protected void applyEntityAttributes() {
	super.applyEntityAttributes();
	getEntityAttribute(SharedMonsterAttributes.knockbackResistance).setBaseValue(1.0D);
	getEntityAttribute(SharedMonsterAttributes.maxHealth).setBaseValue(MAX_HEALTH);
	getEntityAttribute(SharedMonsterAttributes.movementSpeed).setBaseValue(0.0D);
}

public void onLivingUpdate() {
	//WIP
    }

public EnumCreatureAttribute getCreatureAttribute() {
	return EnumCreatureAttribute.UNDEFINED;
}

protected void entityInit() {
        super.entityInit();
    }

public void writeToNBT(NBTTagCompound nbttagcompound) {
	super.writeToNBT(nbttagcompound);
}

public void readFromNBT(NBTTagCompound nbttagcompound) {
	super.readFromNBT(nbttagcompound);
}

public boolean attackEntityFromPart(EntityDragonPart dragonPart, DamageSource dmgSrc, float f0) {
	int armoredDamage = Math.round(f0 / ARMOR_MULTIPLIER);
	double range = calculateRange(dmgSrc);
	if (range > 14D)
            return false;
	else
            return superAttackFrom(dmgSrc, armoredDamage);
}

protected boolean superAttackFrom(DamageSource dmgSrc, float f0) {
        return super.attackEntityFrom(dmgSrc, f0);
    }

protected double calculateRange(DamageSource dmgSrc) {
        double range = -1D;
        if (dmgSrc.getEntity() != null) {
            range = getDistanceSqToEntity(dmgSrc.getEntity());
        }
        if (dmgSrc.getSourceOfDamage() != null) {
            range = getDistanceSqToEntity(dmgSrc.getSourceOfDamage());
        }
        return range;
    }

public boolean attackEntityFrom(DamageSource dmgSrc, float f0) {
        return false;
    }

public Entity[] getParts() {
        return partArray;
    }

public boolean isEntityInvulnerable() {
	return false;
}

public boolean canDespawn() {
	return false;
}

public void knockBack(Entity entity1, float f, double d2, double d3) {}

protected String getLivingSound() {
        return "mob.enderdragon.growl";//Test sounds
    }

protected String getHurtSound() {
        return "mob.enderdragon.hit";
    }

protected String getDeathSound() {
	return "mob.enderdragon.death";
}

protected float getSoundVolume() {
        return 2.0F;
    }

public void onDeath(DamageSource dmgSrc) {
        super.onDeath(dmgSrc);
    }

protected void dropFewItems(boolean par1, int par2) {
	//WIP
}

protected boolean isAIEnabled() {
	return false;
}

public boolean canBeCollidedWith() {
        return true;
    }

protected void onDeathUpdate() {
	//Death anim stuff here
}

public World func_82194_d() {
	return worldObj;
}
}

 

My first issue that I've come across is that whenever I attempt to attack my entity, it doesn't take damage. I realize I set the attackEntityFrom to return false, but I want to be able to tell which hitbox of the entity was hit (I assumed attackEntityFromPart would do the trick). How can I fix this?

 

I also have a question: does each sub-entity of the mob have to be my own custom part entity, or can they just be dragonParts?

 

You'd do this by moving the parent entity part and the onUpdate() method

Should I be using onUpdate() or onLivingUpdate()?

 

Finally, here is a picture of the mob (WIP). Each box is intended to have its own hitbox, including the parent entity on the bottom.

Link to comment
Share on other sites

Okay, so you can see that Entity Dragon pretty much takes the approach I mentioned -- when you construct the parent part, it creates an array of child parts which get the parent part passed to them.

 

A few comments:

- I don't think you need all those fields for each part. You already have an array of parts, so you shouldn't need a field for tendrilBase1, tendrilBase2, etc. I know that Ender Dragon does do that, but it isn't really needed -- you can reference tendrilBase3 with tendrilBase[3] and there is a string which can give the part a nice name if you need it.

- When you construct the parts, you have them all set the same size (hitbox size). Is that what you want? Your picture makes it look like they'll get smaller and smaller. In Ender Dragon, it set's the hitboxes later but you can set them right when you construct them in the array of parts.

 

Anyway, I think the main problem I see though is: where do you set the position of the parts? When you create them they'll be at 0, 0, 0 so you need to set their position. The Ender Dragon does this in the onLivingUpdate() method where you can see it has a for loop that goes through all the parts and updates their position.

 

Regarding using onUpdate() or onLivingUpdate(), there are lots of methods that are called every tick and that is the main thing that matters. onLivingUpdate() makes good logical sense, so use that.

 

By the way, you probably already know, but by pressing F3+B you can see all the entity bounding boxes. This would be useful while testing a multi-part entity.

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

Link to comment
Share on other sites

Why are you trying to make a multipart entity?  Hitboxes?

Correct.

Anyway, I think the main problem I see though is: where do you set the position of the parts? When you create them they'll be at 0, 0, 0 so you need to set their position. The Ender Dragon does this in the onLivingUpdate() method where you can see it has a for loop that goes through all the parts and updates their position.

Do you mean something like this:

public void onLivingUpdate() {
	int prevHeight = 0;
	for (int i = 0; i < partArray.length; i++) {
		partArray[i].setPosition(0, ((30 - (2 * i)) / 16) + prevHeight, 0);
		prevHeight = ((30 - (2 * i)) / 16) + prevHeight;
	}
    }

I ran the game with that bit of code in, but I still can't hit it correctly. Is there a way I could see the hitboxes so I can position them better, or is that not the issue?

Link to comment
Share on other sites

Is there a way I could see the hitboxes so I can position them better?

By the way, you probably already know, but by pressing F3+B you can see all the entity bounding boxes. This would be useful while testing a multi-part entity.

bounding boxes = hit boxes

Link to comment
Share on other sites

partArray[i].setPosition(0, ((30 - (2 * i)) / 16) + prevHeight, 0);

You set the position relative to 0,0,0. You need to set the relative to the main entity's coordinates (posX,posY,posZ).

Don't PM me with questions. They will be ignored! Make a thread on the appropriate board for support.

 

1.12 -> 1.13 primer by williewillus.

 

1.7.10 and older versions of Minecraft are no longer supported due to it's age! Update to the latest version for support.

 

http://www.howoldisminecraft1710.today/

Link to comment
Share on other sites

Alright, so I changed the code to:

double prevHeight = posY;
	for (int i = 0; i < partArray.length; i++) {
		partArray[i].setPosition(posX, ((30 - (2 * i)) / 16) + prevHeight, posZ);
		prevHeight = ((30 - (2 * i)) / 16) + prevHeight;
	}

However, nothing appears to have changed. Did I do it wrong?

Link to comment
Share on other sites

For debugging you should learn to use console statements. Just add System.out.println() type statements at each point in your code to print out stuff that helps you see what it is actually doing. So I would suggest printing out the positions in the loop that creates the parts.

 

It might also be helpful to have print statements inside the parts' code. Instead of using the built-in EntityDragonPart class, maybe copy that to your own class. Then you can do things like override methods and add print statements, or you can have it print out the position in the onUpdate() method, etc. You'll have more control with your own class.

 

Anyway, if you print out information that shows what your code is doing, you should be able to quickly figure out what is going wrong.

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

Link to comment
Share on other sites

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



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • I want to make a tree decorator that will generate a beehive under branches of my tree. I have no idea how to check for branches and make beehives generate because TreeDecorator.Context.logs() is just a block pos and i dont understand how it works. i hope ill get an answer here.
    • Imagine this: you've painstakingly accumulated $97,000 worth of Bitcoin, only to see it vanish into the digital abyss at the hands of cunning scammers. It's a devastating blow, leaving you feeling helpless and betrayed. But fear not, for Lee Ultimate Hacker is here to turn the tide in your favor. After conducting extensive research on cryptocurrency recovery options, I stumbled upon Lee Ultimate Hacker, and it proved to be the most suitable choice for the daunting task at hand. Despite my initial skepticism, they shattered my doubts by successfully retrieving $92,000 of the lost Bitcoin—a feat I once deemed impossible. From the moment I reached out to Lee Ultimate Hacker and provided them with all the pertinent information about the fraudulent transaction, they sprang into action with unwavering determination. True to their word, they delivered on their promise to recover the lost Bitcoin within an impressive timeframe of 24 to 72 hours. Their professionalism, expertise, and commitment to their clients were truly commendable, transforming what seemed like an insurmountable ordeal into a resounding triumph. In my eyes, the investment of both time and money was more than justified by the remarkable outcome achieved by Lee Ultimate Hacker. So, if you've fallen victim to cryptocurrency scams and are grappling with the anguish of lost funds, don't despair. Reach out to Lee Ultimate Hacker and let them work their magic. Their track record of success speaks for itself, and with their assistance, you can reclaim what's rightfully yours and emerge stronger than ever before. Don't let the darkness of cybercrime overshadow your financial future. Take a stand against fraudsters with the help of Lee Ultimate Hacker, and witness the transformation from despair to triumph. Your journey to recovery starts here. LEEULTIMATEHACKER@ AOL. COM or Support @ leeultimatehacker . com. telegram:LEEULTIMATE or wh@tsapp +1  (715) 314  -  9248 https://leeultimatehacker.com Thank you.
    • There's a scheme I got into where they promised to trade Bitcoin for me and take a cut as a commission. Seemed like a good idea at the time. But then, things went south real fast. They ended up transferring   $190,000 worth of my Bitcoin. I was devastated and felt completely helpless. That's when I stumbled upon the Wizard Web Recovery Tool. It was like a beacon of hope amid chaos. With this tool, I could finally start digging into what went wrong and hopefully get my Bitcoin back. Using Wizard Web was surprisingly easy. I just had to plug in some details about my Bitcoin account and let it do its thing. It started scanning the internet, looking for any clues about what happened to my Bitcoin. It felt like having a detective on my side, searching for answers. And guess what? Wizard Web found some leads. It uncovered evidence of the scheme's shady dealings and helped me track down the people responsible for losing my Bitcoin. Armed with this information, I took the case to court. After a long and hard-fought legal battle, the court ruled in my favor. The perpetrators were held accountable for their actions and faced criminal charges for their involvement in the scheme. It was a victory not just for me, but for anyone who's been taken advantage of by these kinds of scams. Thanks to Wizard Web Recovery, I was able to get justice and reclaim what was rightfully mine. It showed me that even in the face of adversity, there's always a way to fight back. And with the right tools and determination, anything is possible.   The following is the contact information for Wizard Web Recovery.   Email: wizard web recovery((@))programmer . net
    • Hello, good morning. I know some programming and I'm interested in mod creation. That's why I've decided to follow a tutorial guide on YouTube by TurtyWurty. https://www.youtube.com/watch?v=DhoX9cmAZqA&t=160s&ab_channel=TurtyWurty I've followed the tutorial perfectly. The problem is that when checking the food, the texture doesn't load for me. However, everything seems fine no matter how much I check. I'm sure it's something trivial, the problem is that I can't find it. Could you help me solve it, please? I leave a zip of my file so you can edit it freely. forge-1.20-Civicraft.rar
    • If you have nvidia graphics, it's important that you make sure Minecraft (and anything Minecraft-related) is set to prefer high performance graphics first. If you only update your AMD drivers it might fix the issue but cause severe performance loss vs Vanilla as it'll be running on the integrated graphics instead of dedicated nvidia graphics
  • Topics

×
×
  • Create New...

Important Information

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