_Cruelar_ Posted August 5, 2018 Posted August 5, 2018 Hi guys, I'm working on a Entity, Stone Talus from The Legend of Zelda: Breath of the Wild, which don't take any damage of getting hit except at an ore deposit located on his back. I thought about a second hitbox as a weak spot located at the deposit, but I've no Code yet for the weak spot, because I don't know how to start, but I'll look if I find a way to start, so maybe I can give the code soon. Quote My Projects: Cruelars Triforcemod (1.12 release; 1.14 alpha soon coming) Important: As my mod is on at least 10 different third party sites without my permission, I want to warn you about that with a link to StopModReposts
V0idWa1k3r Posted August 5, 2018 Posted August 5, 2018 As far as I know minecraft only supports one hitbox per entity and there is no way to lift this limitation. If you want multiple hitboxes you need to use multiple entities(some kind of a "parent" entity that handles all the logic and "child" entities that handle the damage). I believe vanilla already does something similar with the enderdragon so that might be a good place to start. Quote
_Cruelar_ Posted August 5, 2018 Author Posted August 5, 2018 Thanks but how it binds the MUltiParts to the ModelParts My Code (AI is only for testing I'm working on a better one): package com.cruelar.cruelars_triforcemod.entities.boss; import com.cruelar.cruelars_triforcemod.Cruelars_Triforcemod_Core; import jline.internal.Nullable; import net.minecraft.entity.*; import net.minecraft.entity.ai.*; import net.minecraft.entity.monster.EntityIronGolem; import net.minecraft.entity.monster.EntityMob; import net.minecraft.entity.monster.EntityPigZombie; import net.minecraft.entity.passive.EntityVillager; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.DamageSource; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.world.BossInfo; import net.minecraft.world.BossInfoServer; import net.minecraft.world.World; public class Stone_Talus extends EntityMob implements IEntityMultiPart { public static final ResourceLocation LOOT = new ResourceLocation(Cruelars_Triforcemod_Core.MODID,"entities/stone_talus.json"); public static final ResourceLocation RESOURCE_LOCATION = new ResourceLocation("cruelars_triforcemod:textures/entity/stone_talus.png"); private final BossInfoServer bossInfo; public final MultiPartEntityPart[] talusParts; public final MultiPartEntityPart Mainbody = new MultiPartEntityPart(this,"mainbody",8,8); public final MultiPartEntityPart Oredeposit = new MultiPartEntityPart(this,"oredeposit",1,1); public Stone_Talus(World world){ super(world); this.setSize(2.0F,3.5F ); this.isNonBoss(); this.setEntityBoundingBox(new AxisAlignedBB(this.getEntityBoundingBox().minX-2,this.getEntityBoundingBox().minY,this.getEntityBoundingBox().minZ,this.getEntityBoundingBox().maxX+2,this.getEntityBoundingBox().maxY+4,this.getEntityBoundingBox().maxZ)); this.bossInfo = (BossInfoServer)(new BossInfoServer(this.getDisplayName(), BossInfo.Color.RED, BossInfo.Overlay.PROGRESS)); this.isImmuneToFire = true; this.talusParts=new MultiPartEntityPart[]{this.Mainbody,this.Oredeposit}; } public void readEntityFromNBT(NBTTagCompound p_readEntityFromNBT_1_) { super.readEntityFromNBT(p_readEntityFromNBT_1_); if (this.hasCustomName()) { this.bossInfo.setName(this.getDisplayName()); } } protected void updateAITasks() { super.updateAITasks(); this.bossInfo.setPercent(this.getHealth() / this.getMaxHealth()); } public void addTrackingPlayer(EntityPlayerMP p_addTrackingPlayer_1_) { super.addTrackingPlayer(p_addTrackingPlayer_1_); this.bossInfo.addPlayer(p_addTrackingPlayer_1_); } public void removeTrackingPlayer(EntityPlayerMP p_removeTrackingPlayer_1_) { super.removeTrackingPlayer(p_removeTrackingPlayer_1_); this.bossInfo.removePlayer(p_removeTrackingPlayer_1_); } public void setCustomNameTag(String p_setCustomNameTag_1_) { super.setCustomNameTag(p_setCustomNameTag_1_); this.bossInfo.setName(this.getDisplayName()); } @Override protected void entityInit(){ super.entityInit(); } @Override protected void applyEntityAttributes(){ super.applyEntityAttributes(); this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(300.0D); this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0.1D); this.getEntityAttribute(SharedMonsterAttributes.ARMOR).setBaseValue(10.0D); this.getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE).setBaseValue(32.0D); this.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).setBaseValue(10.0D); this.getEntityAttribute(SharedMonsterAttributes.KNOCKBACK_RESISTANCE).setBaseValue(100.0D); } @Override protected void initEntityAI(){ this.tasks.addTask(0,new EntityAISwimming(this)); this.tasks.addTask(2,new EntityAIAttackMelee(this,1.0D,true)); this.tasks.addTask(5,new EntityAIMoveTowardsRestriction(this,1.0D)); this.tasks.addTask(7,new EntityAIWander(this,1.0D)); this.tasks.addTask(8,new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F)); this.tasks.addTask(8,new EntityAILookIdle(this)); this.applyEntityAI(); } private void applyEntityAI() { this.tasks.addTask(6, new EntityAIMoveThroughVillage(this, 1.0D, false)); this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, true, EntityPigZombie.class)); this.targetTasks.addTask(2, new EntityAINearestAttackableTarget<>(this, EntityPlayer.class, true)); this.targetTasks.addTask(3, new EntityAINearestAttackableTarget<>(this, EntityVillager.class, true)); this.targetTasks.addTask(3, new EntityAINearestAttackableTarget<>(this, EntityIronGolem.class, true)); } @Override public boolean attackEntityAsMob(Entity entity){ return super.attackEntityAsMob(entity); } @Override @Nullable protected ResourceLocation getLootTable(){ return LOOT; } @Override protected boolean isValidLightLevel(){ return true; } @Override protected boolean canDropLoot () { return true; } @Override public int getMaxSpawnedInChunk(){ return 1; } @Override public boolean isNonBoss(){ return false; } @Override public World getWorld() { return this.world; } @Override public boolean attackEntityFromPart(MultiPartEntityPart entityPart, DamageSource source, float damage) { if (entityPart==Oredeposit){ return true; } return false; } } Quote My Projects: Cruelars Triforcemod (1.12 release; 1.14 alpha soon coming) Important: As my mod is on at least 10 different third party sites without my permission, I want to warn you about that with a link to StopModReposts
V0idWa1k3r Posted August 5, 2018 Posted August 5, 2018 12 minutes ago, _Cruelar_ said: how it binds the MUltiParts to the ModelParts What do you mean? As far as I know multiparts don't have a model. In case of the dragon it's only the main entity which has the model. Multiparts are purely for collision/damage detection. Quote
_Cruelar_ Posted August 5, 2018 Author Posted August 5, 2018 My Problem is I don't find anything about where the BoundingBox of the MultiPart is located Quote My Projects: Cruelars Triforcemod (1.12 release; 1.14 alpha soon coming) Important: As my mod is on at least 10 different third party sites without my permission, I want to warn you about that with a link to StopModReposts
V0idWa1k3r Posted August 5, 2018 Posted August 5, 2018 When you instantinate the multipart you specify the width and the height of it. Those are the dimensions of your bounding box. Then somewhere(presumably in your entity's update method) you update the positions of your multiparts using Entity#setLocationAndAngles. That also updates the position of the bounding box of that entity. See how EntityDragon handles the multipart positions in it's onLivingUpdate method. Quote
_Cruelar_ Posted August 6, 2018 Author Posted August 6, 2018 Still doesn't work.I can't see the Hitbox when I press F3+B. What' is wrong? package com.cruelar.cruelars_triforcemod.entities.boss; import com.cruelar.cruelars_triforcemod.Cruelars_Triforcemod_Core; import jline.internal.Nullable; import net.minecraft.entity.*; import net.minecraft.entity.ai.*; import net.minecraft.entity.monster.EntityIronGolem; import net.minecraft.entity.monster.EntityMob; import net.minecraft.entity.monster.EntityPigZombie; import net.minecraft.entity.passive.EntityVillager; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.DamageSource; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.world.BossInfo; import net.minecraft.world.BossInfoServer; import net.minecraft.world.World; public class Stone_Talus extends EntityMob implements IEntityMultiPart { public static final ResourceLocation LOOT = new ResourceLocation(Cruelars_Triforcemod_Core.MODID, "entities/stone_talus.json"); public static final ResourceLocation RESOURCE_LOCATION = new ResourceLocation("cruelars_triforcemod:textures/entity/stone_talus.png"); private final BossInfoServer bossInfo; public final MultiPartEntityPart[] talusParts; public final MultiPartEntityPart Mainbody = new MultiPartEntityPart(this, "mainbody", 5, 5); public final MultiPartEntityPart Oredeposit = new MultiPartEntityPart(this, "oredeposit", 1, 1); public float prevAnimTime; public float animTime; public Stone_Talus(World world) { super(world); this.setSize(2.0F, 3.5F); this.isNonBoss(); this.setHealth(this.getMaxHealth()); this.bossInfo = (BossInfoServer) (new BossInfoServer(this.getDisplayName(), BossInfo.Color.RED, BossInfo.Overlay.PROGRESS)); this.isImmuneToFire = true; this.talusParts = new MultiPartEntityPart[]{this.Mainbody, this.Oredeposit}; } public void readEntityFromNBT(NBTTagCompound p_readEntityFromNBT_1_) { super.readEntityFromNBT(p_readEntityFromNBT_1_); if (this.hasCustomName()) { this.bossInfo.setName(this.getDisplayName()); } } protected void updateAITasks() { super.updateAITasks(); } public void addTrackingPlayer(EntityPlayerMP p_addTrackingPlayer_1_) { super.addTrackingPlayer(p_addTrackingPlayer_1_); this.bossInfo.addPlayer(p_addTrackingPlayer_1_); } public void removeTrackingPlayer(EntityPlayerMP p_removeTrackingPlayer_1_) { super.removeTrackingPlayer(p_removeTrackingPlayer_1_); this.bossInfo.removePlayer(p_removeTrackingPlayer_1_); } public void setCustomNameTag(String p_setCustomNameTag_1_) { super.setCustomNameTag(p_setCustomNameTag_1_); this.bossInfo.setName(this.getDisplayName()); } @Override protected void entityInit() { super.entityInit(); } @Override protected void applyEntityAttributes() { super.applyEntityAttributes(); this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(300.0D); this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0.1D); this.getEntityAttribute(SharedMonsterAttributes.ARMOR).setBaseValue(10.0D); this.getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE).setBaseValue(32.0D); this.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).setBaseValue(10.0D); this.getEntityAttribute(SharedMonsterAttributes.KNOCKBACK_RESISTANCE).setBaseValue(100.0D); } @Override protected void initEntityAI() { this.tasks.addTask(0, new EntityAISwimming(this)); this.tasks.addTask(2, new EntityAIAttackMelee(this, 1.0D, true)); this.tasks.addTask(5, new EntityAIMoveTowardsRestriction(this, 1.0D)); this.tasks.addTask(7, new EntityAIWander(this, 1.0D)); this.tasks.addTask(8, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F)); this.tasks.addTask(8, new EntityAILookIdle(this)); this.applyEntityAI(); } private void applyEntityAI() { this.tasks.addTask(6, new EntityAIMoveThroughVillage(this, 1.0D, false)); this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, true, EntityPigZombie.class)); this.targetTasks.addTask(2, new EntityAINearestAttackableTarget<>(this, EntityPlayer.class, true)); this.targetTasks.addTask(3, new EntityAINearestAttackableTarget<>(this, EntityVillager.class, true)); this.targetTasks.addTask(3, new EntityAINearestAttackableTarget<>(this, EntityIronGolem.class, true)); } @Override public boolean attackEntityAsMob(Entity entity) { return super.attackEntityAsMob(entity); } @Override @Nullable protected ResourceLocation getLootTable() { return LOOT; } @Override protected boolean isValidLightLevel() { return true; } @Override protected boolean canDropLoot() { return true; } @Override public int getMaxSpawnedInChunk() { return 1; } @Override public boolean isNonBoss() { return false; } @Override public World getWorld() { return this.world; } @Override public boolean attackEntityFromPart(MultiPartEntityPart entityPart, DamageSource source, float damage) { return entityPart == Oredeposit; } @Override public void onLivingUpdate() { if (this.world.isRemote) { this.setHealth(this.getHealth()); } this.prevAnimTime = this.animTime; if (this.getHealth() <= 0.0F) { float f12 = (this.rand.nextFloat() - 0.5F) * 8.0F; float f13 = (this.rand.nextFloat() - 0.5F) * 4.0F; float f15 = (this.rand.nextFloat() - 0.5F) * 8.0F; this.world.spawnParticle(EnumParticleTypes.SPELL_MOB_AMBIENT, this.posX + (double) f12, this.posY + 2.0D + (double) f13, this.posZ + (double) f15, 0.0D, 0.0D, 0.0D); } if (this.isAIDisabled()) { this.animTime = 0.5F; } else { Mainbody.onUpdate(); Mainbody.setLocationAndAngles(this.posX, this.posY, this.posZ, 0, 0); Oredeposit.onUpdate(); Oredeposit.setLocationAndAngles(this.posX + 1, this.posY + 4, this.posZ, 0, 0); } this.bossInfo.setPercent(this.getHealth() / this.getMaxHealth()); } } Quote My Projects: Cruelars Triforcemod (1.12 release; 1.14 alpha soon coming) Important: As my mod is on at least 10 different third party sites without my permission, I want to warn you about that with a link to StopModReposts
_Cruelar_ Posted August 9, 2018 Author Posted August 9, 2018 (edited) I just noticed the Entity now also has no Ai anymore.☹️ Edited August 9, 2018 by _Cruelar_ Quote My Projects: Cruelars Triforcemod (1.12 release; 1.14 alpha soon coming) Important: As my mod is on at least 10 different third party sites without my permission, I want to warn you about that with a link to StopModReposts
_Cruelar_ Posted August 13, 2018 Author Posted August 13, 2018 Could anyone explain to me if this is always the case when using IEntityMultiPart. Quote My Projects: Cruelars Triforcemod (1.12 release; 1.14 alpha soon coming) Important: As my mod is on at least 10 different third party sites without my permission, I want to warn you about that with a link to StopModReposts
_Cruelar_ Posted August 23, 2018 Author Posted August 23, 2018 (edited) I fixed the ai. I forgot to call super.onLivingUpdate. Still The Hitboxes aren't showing. My Entity code: package com.cruelar.cruelars_triforcemod.entities.boss; import com.cruelar.cruelars_triforcemod.Cruelars_Triforcemod_Core; import net.minecraft.entity.*; import net.minecraft.entity.ai.*; import net.minecraft.entity.monster.EntityMob; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.DamageSource; import net.minecraft.util.EntityDamageSource; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.Vec3d; import net.minecraft.world.BossInfo; import net.minecraft.world.BossInfoServer; import net.minecraft.world.DifficultyInstance; import net.minecraft.world.World; import javax.annotation.Nonnull; import javax.annotation.Nullable; public class Stone_Talus extends EntityMob implements IEntityMultiPart { public static final ResourceLocation LOOT = new ResourceLocation("cruelars_triforcemod:entities/stone_talus"); public static final ResourceLocation RESOURCE_LOCATION = new ResourceLocation("cruelars_triforcemod:textures/entity/stone_talus.png"); private final BossInfoServer bossInfo; public MultiPartEntityPart[] talusParts; public MultiPartEntityPart Mainbody; public MultiPartEntityPart Oredeposit; public float prevAnimTime; public float animTime; public Stone_Talus(World world) { super(world); this.setSize(2.0F, 5F); this.isNonBoss(); this.bossInfo = (BossInfoServer) (new BossInfoServer(this.getDisplayName(), BossInfo.Color.RED, BossInfo.Overlay.PROGRESS)); this.isImmuneToFire = true; this.Mainbody= new MultiPartEntityPart(this, "mainbody", 2, 2); this.Oredeposit = new MultiPartEntityPart(this, "oredeposit", 1, 1); this.talusParts=new MultiPartEntityPart[]{this.Oredeposit,this.Mainbody}; } public void readEntityFromNBT(NBTTagCompound p_readEntityFromNBT_1_) { super.readEntityFromNBT(p_readEntityFromNBT_1_); if (this.hasCustomName()) { this.bossInfo.setName(this.getDisplayName()); } } protected void updateAITasks() { super.updateAITasks(); } public void addTrackingPlayer(EntityPlayerMP p_addTrackingPlayer_1_) { float distance = p_addTrackingPlayer_1_.getDistance(this); if (distance<=10) { super.addTrackingPlayer(p_addTrackingPlayer_1_); this.bossInfo.addPlayer(p_addTrackingPlayer_1_); } } public void removeTrackingPlayer(EntityPlayerMP p_removeTrackingPlayer_1_) { super.removeTrackingPlayer(p_removeTrackingPlayer_1_); this.bossInfo.removePlayer(p_removeTrackingPlayer_1_); } public void setCustomNameTag(String p_setCustomNameTag_1_) { super.setCustomNameTag(p_setCustomNameTag_1_); this.bossInfo.setName(this.getDisplayName()); } @Override protected void entityInit() { super.entityInit(); } @Override protected void applyEntityAttributes() { super.applyEntityAttributes(); this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(300.0D); this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0.1D); this.getEntityAttribute(SharedMonsterAttributes.ARMOR).setBaseValue(10.0D); this.getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE).setBaseValue(32.0D); this.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).setBaseValue(10.0D); this.getEntityAttribute(SharedMonsterAttributes.KNOCKBACK_RESISTANCE).setBaseValue(100.0D); } @Override protected void initEntityAI() { this.tasks.addTask(2, new EntityAIAttackMelee(this, 1.0D, true)); this.tasks.addTask(5, new EntityAIMoveTowardsRestriction(this, 1.0D)); this.tasks.addTask(7, new EntityAIWander(this, 1.0D)); this.tasks.addTask(8, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F)); this.tasks.addTask(8, new EntityAILookIdle(this)); this.applyEntityAI(); } private void applyEntityAI() { this.targetTasks.addTask(2, new EntityAINearestAttackableTarget<>(this, EntityPlayer.class, true)); } @Override public boolean attackEntityAsMob(Entity entity) { return super.attackEntityAsMob(entity); } @Override @Nonnull protected ResourceLocation getLootTable() { return LOOT; } @Override protected boolean isValidLightLevel() { return true; } @Override protected boolean canDropLoot() { return true; } @Override public int getMaxSpawnedInChunk() { return 1; } @Override public boolean isNonBoss() { return false; } @Override public World getWorld() { return this.world; } public boolean attackEntityFrom(DamageSource source, float amount) { if (source instanceof EntityDamageSource && ((EntityDamageSource)source).getIsThornsDamage()) { this.attackEntityFromPart(this.Oredeposit, source, amount); } this.attackEntityFromPart(this.Oredeposit, source, amount); return true; } protected boolean attackTalusFrom(DamageSource source, float amount) { return super.attackEntityFrom(source, amount); } @Override public void onLivingUpdate() { super.onLivingUpdate(); if (this.world.isRemote) { if (this.talusParts[0]==null||this.talusParts[1]==null){ this.talusParts = new MultiPartEntityPart[]{this.Mainbody= new MultiPartEntityPart(this, "mainbody", 5, 5), this.Oredeposit = new MultiPartEntityPart(this, "oredeposit", 1, 1)}; } this.setHealth(this.getHealth()); }else{ this.move(MoverType.SELF, this.motionX, this.motionY, this.motionZ); Vec3d vec3d3 = (new Vec3d(this.motionX, this.motionY, this.motionZ)).normalize(); float f10 = 0.8F + 0.15F * 0.1F; this.motionX *= (double)f10; this.motionZ *= (double)f10; this.motionY *= 0.9100000262260437D; Vec3d[] avec3d = new Vec3d[this.talusParts.length]; for (int j = 0; j < this.talusParts.length; ++j) { avec3d[j] = new Vec3d(this.talusParts[j].posX, this.talusParts[j].posY, this.talusParts[j].posZ); } this.prevAnimTime = this.animTime; if (this.getHealth() <= 0.0F) { float f12 = (this.rand.nextFloat() - 0.5F) * 8.0F; float f13 = (this.rand.nextFloat() - 0.5F) * 4.0F; float f15 = (this.rand.nextFloat() - 0.5F) * 8.0F; this.world.spawnParticle(EnumParticleTypes.SPELL_MOB_AMBIENT, this.posX + (double) f12, this.posY + 2.0D + (double) f13, this.posZ + (double) f15, 0.0D, 0.0D, 0.0D); }else { if (this.isAIDisabled()) { this.animTime = 0.5F; } else { Mainbody.onUpdate(); Mainbody.setLocationAndAngles(this.posX, this.posY, this.posZ, 0, 0); Oredeposit.onUpdate(); Oredeposit.setLocationAndAngles(this.posX + 1, this.posY + 2, this.posZ, 0, 0); for (int l = 0; l < this.talusParts.length; ++l) { this.talusParts[l].prevPosX = avec3d[l].x; this.talusParts[l].prevPosY = avec3d[l].y; this.talusParts[l].prevPosZ = avec3d[l].z; } } this.bossInfo.setPercent(this.getHealth() / this.getMaxHealth()); } } } @Override public void onKillCommand() { this.setDead(); } @Nullable @Override public IEntityLivingData onInitialSpawn(DifficultyInstance difficulty, @Nullable IEntityLivingData livingdata) { this.Mainbody= new MultiPartEntityPart(this, "mainbody", 2, 2); this.Oredeposit = new MultiPartEntityPart(this, "oredeposit", 1, 1); this.talusParts = new MultiPartEntityPart[]{this.Mainbody, this.Oredeposit}; return livingdata; } public Entity[] getParts() { return this.talusParts; } public boolean attackEntityFromPart(MultiPartEntityPart talusPart, DamageSource source, float damage) { if (damage < 0.01F) { return false; } else { if (source.getTrueSource() instanceof EntityPlayer || source.isExplosion()) { float f = this.getHealth(); this.attackTalusFrom(source, damage); } return true; } } } Edited August 23, 2018 by _Cruelar_ typo Quote My Projects: Cruelars Triforcemod (1.12 release; 1.14 alpha soon coming) Important: As my mod is on at least 10 different third party sites without my permission, I want to warn you about that with a link to StopModReposts
Recommended Posts
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.