Résolu Problèmes sur les entités
-
Salut !
(Décidément, j’ai décidé de vous casser les pieds… Bon cette fois c’est un problème de mathématiques (faut pas compter sur moi pour le résoudre :P))
Il y a peu, j’ai crée une tourelle et je rencontre divers petits problèmes. Je compte sur vous pour me mettre sur la bonne voie car je suis complètement perdu, ayant tout essayé.- Ma tourelle pivote. Je voudrais la rendre fixe car elle est liée à un bloc. J’ai réussi à la rendre fixe, mais elle est capable de tourner sur elle-même, en plus de bouger la tête.
- Ensuite, je n’arrive pas à lier mon TileEntityTurret à mon EntityTurret. Cette méthode me permet de lier la tourelle au bloc.
- Enfin, ma tourelle me regarde lorsque je m’approche, puis regarde dans le vide alors qu’elle est censée regarder le mob qu’elle attaque alors que dans mon entityUpdate() j’ai mis : this.getLookHelper().setLookPositionWithEntity(this.getAttackTarget(), 10.0F, (float)this.getVerticalFaceSpeed());
TileEntityTurret.class :
package fr.wirestone.entity; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraftforge.common.DimensionManager; public class TileEntityTurret extends TileEntity{ private EntityTurret turret; public TileEntityTurret(){ super(); } @Override public void writeToNBT(NBTTagCompound nbt){ super.writeToNBT(nbt); nbt.setInteger("worldID", this.worldObj.provider.dimensionId); nbt.setInteger("entityID", this.turret.getEntityId()); } @Override public void readFromNBT(NBTTagCompound nbt){ super.readFromNBT(nbt); this.turret = (EntityTurret)DimensionManager.getProvider(nbt.getInteger("worldID")).worldObj.getEntityByID(nbt.getInteger("entityID")); System.out.println(this.turret); } public void setLinkedTurret(){ if(this.turret != null){ this.turret.setDead(); } this.turret = new EntityTurret(this.worldObj, this.xCoord + 0.5, this.yCoord + 1, this.zCoord + 0.5); this.worldObj.spawnEntityInWorld(this.turret); } public EntityTurret getLinkedTurret(){ return this.turret; } }
EntityTurret.class :
package fr.wirestone.entity; import java.util.ArrayList; import java.util.Collections; import java.util.List; import net.minecraft.command.IEntitySelector; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLiving; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.SharedMonsterAttributes; import net.minecraft.entity.ai.EntityAILookIdle; import net.minecraft.entity.ai.EntityAINearestAttackableTarget; import net.minecraft.entity.ai.EntityAINearestAttackableTarget.Sorter; import net.minecraft.entity.ai.EntityAIWatchClosest; import net.minecraft.entity.monster.EntityMob; import net.minecraft.entity.monster.IMob; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.Vec3; import net.minecraft.world.World; import com.flansmod.client.model.ModelBullet; import com.flansmod.common.guns.BulletType; import com.flansmod.common.guns.EntityBullet; import com.flansmod.common.types.EnumType; import com.flansmod.common.types.TypeFile; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import fr.wirestone.core.WirestoneModLogger; public class EntityTurret extends EntityLiving{ public static final int MAX_RANGE = 40; public static final int SHOT_DELAY = 5; public static final BulletType BULLET_TYPE; private final Class targets = IMob.class; private Sorter entitySorter; private int ticks; static{ ArrayList <string>lines = new ArrayList<string>(); lines.add("FallSpeed 0.2"); lines.add("BreaksGlass false"); lines.add("SmokeTrail true"); TypeFile file = new TypeFile(EnumType.bullet, "TurretBullet"); file.lines = lines; BULLET_TYPE = new BulletType(file); BULLET_TYPE.shortName = "AutoTurret"; BULLET_TYPE.model = new ModelBullet(); } public EntityTurret(World w){ super(w); this.initialize(); } public EntityTurret(World w, double x, double y, double z){ this(w); this.setPosition(x, y, z); } private void initialize(){ this.setSize(1.0F, 1.4F); this.isImmuneToFire = true; this.jumpMovementFactor = 0.0F; this.setAIMoveSpeed(0.0F); this.entitySorter = new EntityAINearestAttackableTarget.Sorter(this); } @Override public void applyEntityAttributes(){ super.applyEntityAttributes(); this.getEntityAttribute(SharedMonsterAttributes.maxHealth).setBaseValue(40.0D); this.getEntityAttribute(SharedMonsterAttributes.movementSpeed).setBaseValue(0.0D); } @Override public void onLivingUpdate(){ super.onLivingUpdate(); } @Override public boolean canAttackClass(Class clazz){ return clazz.getGenericSuperclass().equals(EntityMob.class); } @Override public void updateEntityActionState(){ super.updateEntityActionState(); if(this.shouldShot()){ this.getLookHelper().setLookPositionWithEntity(this.getAttackTarget(), 10.0F, (float)this.getVerticalFaceSpeed()); this.shot(); } } private boolean shouldShot(){ if(this.hasAttackTarget()){ if(this.getAttackTarget().isEntityAlive() && this.isAtGoodDistance(this.getAttackTarget()) && this.canSee(this.getAttackTarget())){ return true; } if(this.searchForTargets()){ return true; } this.setAttackTarget(null); this.playClearSound(); return false; } if(this.searchForTargets()){ this.playAttackSound(); return true; } return false; } private boolean searchForTargets(){ List <entitylivingbase>entities = this.worldObj.getEntitiesWithinAABB(this.targets, this.boundingBox.expand(MAX_RANGE, MAX_RANGE, MAX_RANGE)); Collections.sort(entities, this.entitySorter); for(EntityLivingBase i : entities){ if(i.isEntityAlive() && this.canSee(i) && this.isAtGoodDistance(i)){ this.setAttackTarget(i); return true; } } return false; } private boolean isAtGoodDistance(EntityLivingBase target){ return this.getDistanceToEntity(target) <= EntityTurret.MAX_RANGE; } private boolean canSee(EntityLivingBase target){ return this.getEntitySenses().canSee(target); } private boolean hasAttackTarget(){ return this.getAttackTarget() != null; } @Override public void playLivingSound(){ if(this.getAttackTarget() == null){ this.playBipSound(); } } @Override public String getLivingSound(){ return "wsmod:turret-bip"; } @Override public int getTalkInterval(){ return 180; } /** * Fire ! */ public void shot(){ ++this.ticks; if(this.getAttackTarget() != null && this.ticks >= SHOT_DELAY){ this.ticks = 0; this.playSound("wsmod:sps", 1.0F, 1.0F); Vec3 origin = Vec3.createVectorHelper(this.posX, this.posY + this.getEyeHeight(), this.posZ); EntityBullet bullet = new EntityBullet(this.worldObj, origin, this.rotationYawHead / (180F / (float) Math.PI), this.rotationPitch, null, 1.0F, 2.0F, BULLET_TYPE, BULLET_TYPE); this.worldObj.spawnEntityInWorld(bullet); } } public void playAttackSound(){ this.playSound("wsmod:turret-target", 0.8F, 1.0F); } public void playBipSound(){ this.playSound("wsmod:turret-bip", 0.8F, 1.0F); } public void playClearSound(){ this.playSound("wsmod:turret-clear", 0.8F, 1.0F); } @Override protected boolean interact(EntityPlayer player){ if(player.worldObj.isRemote && player.getDisplayName().equals("Arthur340") && player.capabilities.isCreativeMode && player.isSneaking()){ WirestoneModLogger.getLogger().info("Suppression forcée de la tourelle x= " + (int)this.posX + ", y= " + (int)this.posY + ", z= " + (int)this.posZ + "."); this.worldObj.removeEntity(this); return true; } return false; } @Override public void readEntityFromNBT(NBTTagCompound tag){ super.readEntityFromNBT(tag); this.ticks = tag.getInteger("ticks1"); } @Override public void writeEntityToNBT(NBTTagCompound tag){ super.writeEntityToNBT(tag); tag.setInteger("ticks1", this.ticks); } @Override public void moveEntity(double x, double y, double z){} @Override public float getEyeHeight(){ return 1.0F; } @Override public boolean canBeCollidedWith(){ return true; } @Override public boolean canBePushed(){ return false; } @Override public boolean canAttackWithItem(){ return true; } @Override public boolean isEntityInvulnerable(){ return true; } @Override public boolean doesEntityNotTriggerPressurePlate(){ return true; } @Override @SideOnly(Side.CLIENT) public boolean canRenderOnFire(){ return false; } @Override public boolean isPushedByWater(){ return false; } /** * Vitesse de rotation de la tête */ @Override public int getVerticalFaceSpeed(){ return 80; } @Override public boolean isNoDespawnRequired(){ return true; } @Override public float getAIMoveSpeed(){ return 0.0F; } }
TurretModel.class :
package fr.wirestone.model; import net.minecraft.client.model.ModelBase; import net.minecraft.client.model.ModelRenderer; import net.minecraft.entity.Entity; public class TurretModel extends ModelBase{ /** * Base */ ModelRenderer base1, base2, base3, axis; /** * Head */ ModelRenderer head, gun1, gun2, header1, header2; public TurretModel(){ textureWidth = 128; textureHeight = 64; base1 = new ModelRenderer(this, 0, 0); base1.addBox(0F, 0F, 0F, 16, 1, 16); base1.setRotationPoint(-8F, 23F, -8F); base1.setTextureSize(128, 64); base1.mirror = true; setRotation(base1, 0F, 0F, 0F); base2 = new ModelRenderer(this, 0, 17); base2.addBox(0F, 0F, 0F, 12, 1, 12); base2.setRotationPoint(-6F, 22F, -6F); base2.setTextureSize(128, 64); base2.mirror = true; setRotation(base2, 0F, 0F, 0F); base3 = new ModelRenderer(this, 0, 30); base3.addBox(0F, 0F, 0F, 8, 1, 8); base3.setRotationPoint(-4F, 21F, -4F); base3.setTextureSize(128, 64); base3.mirror = true; setRotation(base3, 0F, 0F, 0F); axis = new ModelRenderer(this, 48, 17); axis.addBox(0F, 0F, 0F, 2, 13, 2); axis.setRotationPoint(-1F, 8F, -1F); axis.setTextureSize(128, 64); axis.mirror = true; setRotation(axis, 0F, 0F, 0F); head = new ModelRenderer(this, 0, 39); head.addBox(-3F, -2F, -3F, 6, 4, 6); head.setRotationPoint(0F, 7F, 0F); head.setTextureSize(128, 64); head.mirror = true; setRotation(head, 0F, 0F, 0F); gun1 = new ModelRenderer(this, 0, 54); gun1.addBox(-2F, 0F, -7F, 1, 1, 4); gun1.setRotationPoint(0F, 7F, 0F); gun1.setTextureSize(128, 64); gun1.mirror = true; setRotation(gun1, 0F, 0F, 0F); gun2 = new ModelRenderer(this, 0, 49); gun2.addBox(1F, 0F, -7F, 1, 1, 4); gun2.setRotationPoint(0F, 7F, 0F); gun2.setTextureSize(128, 64); gun2.mirror = true; setRotation(gun2, 0F, 0F, 0F); header1 = new ModelRenderer(this, 10, 52); header1.addBox(-2F, -1F, -5F, 1, 1, 2); header1.setRotationPoint(0F, 7F, 0F); header1.setTextureSize(128, 64); header1.mirror = true; setRotation(header1, 0F, 0F, 0F); header2 = new ModelRenderer(this, 10, 49); header2.addBox(1F, -1F, -5F, 1, 1, 2); header2.setRotationPoint(0F, 7F, 0F); header2.setTextureSize(128, 64); header2.mirror = true; setRotation(header2, 0F, 0F, 0F); } @Override public void render(Entity entity, float f, float f1, float f2, float f3, float f4, float f5){ super.render(entity, f, f1, f2, f3, f4, f5); setRotationAngles(f, f1, f2, f3, f4, f5, entity); base1.render(f5); base2.render(f5); base3.render(f5); axis.render(f5); head.render(f5); gun1.render(f5); gun2.render(f5); header1.render(f5); header2.render(f5); } private void setRotation(ModelRenderer model, float x, float y, float z){ model.rotateAngleX = x; model.rotateAngleY = y; model.rotateAngleZ = z; } @Override public void setRotationAngles(float par1, float par2, float par3, float par4, float par5, float par6, Entity entity){ super.setRotationAngles(par1, par2, par3, par4, par5, par6, entity); this.head.rotateAngleX = par5 / (180F / (float) Math.PI); this.head.rotateAngleY = par4 / (180F / (float) Math.PI); this.gun1.rotateAngleX = this.head.rotateAngleX; this.gun1.rotateAngleY = this.head.rotateAngleY; this.gun2.rotateAngleX = this.head.rotateAngleX; this.gun2.rotateAngleY = this.head.rotateAngleY; this.header1.rotateAngleX = this.head.rotateAngleX; this.header1.rotateAngleY = this.head.rotateAngleY; this.header2.rotateAngleX = this.head.rotateAngleX; this.header2.rotateAngleY = this.head.rotateAngleY; } }
Merci d’avance :D</entitylivingbase></string></string>
-
Je ne peux tester et/ou verifier ton code. Mais je me rappelle avoir fait quelque chose de similaire. Il faut donner des valeurs de rotation fixes a rotationYaw et rotationYawHead de l entité.
Sinon je vais essayer de faire une tourelle demain et je t en dirais des nouvellesÉcrit avec Tapatalk depuis mon mobile. Pardonnez les possibles fautes, j’aime juste pas écrire avec mon mobile.
-
@‘jglrxavpok’:
Je ne peux tester et/ou verifier ton code. Mais je me rappelle avoir fait quelque chose de similaire. Il faut donner des valeurs de rotation fixes a rotationYaw et rotationYawHead de l entité.
Sinon je vais essayer de faire une tourelle demain et je t en dirais des nouvellesÉcrit avec Tapatalk depuis mon mobile. Pardonnez les possibles fautes, j’aime juste pas écrire avec mon mobile.
Merci
Je viens d’essayer, le truc fonctionne mais la tête reste fixe (elle ne bouge que sur l’axe Y).
-
Ça fait trop longtemps que j’ai pas moddé donc je n’ai pas réussi à faire la tourelle.
Par contre, je peux te donner quelques pistes:- Utiliser des vecteurs pour savoir si une entitée est dans le champ de vision, cf. https://github.com/Gugu42/RatchetAndClankMod/blob/b566410fb681a40b22692851f9c582588f842e81/java/com/gugu42/rcmod/items/ItemSuckCannon.java#L53-L72
- Bloquer la rotation de la tête
- Faire une classe fille de Entity si possible
- Et pour lier TileEntity et Entity, utilise les coordonnées de la TileEntity/Entity pour récupérer l’autre
-
@‘jglrxavpok’:
Ça fait trop longtemps que j’ai pas moddé donc je n’ai pas réussi à faire la tourelle.
Par contre, je peux te donner quelques pistes:- Utiliser des vecteurs pour savoir si une entitée est dans le champ de vision, cf. https://github.com/Gugu42/RatchetAndClankMod/blob/b566410fb681a40b22692851f9c582588f842e81/java/com/gugu42/rcmod/items/ItemSuckCannon.java#L53-L72
- Bloquer la rotation de la tête
- Faire une classe fille de Entity si possible
- Et pour lier TileEntity et Entity, utilise les coordonnées de la TileEntity/Entity pour récupérer l’autre
- Justement : dans ton code : “entity.canEntityBeSeen(owner)”, et c’est ce que j’utilise
- Si je bloque la tête, ma tourelle va tirer toujours tout droit non ?
- Wow… ça va demander du boulot. Mais ok je me lance
- Les coordonnées ? Je vais essayer…
-
@‘EclipseOnFire’:
- Justement : dans ton code : “entity.canEntityBeSeen(owner)”, et c’est ce que j’utilise
- Si je bloque la tête, ma tourelle va tirer toujours tout droit non ?
- Wow… ça va demander du boulot. Mais ok je me lance
- Les coordonnées ? Je vais essayer…
- Il n’y a pas que ça. La partie avec les vecteurs est super importante, entity.canBeSeen vérifie juste que 'y a pas de blocs entre les deux.
- Oui, mais tu peux toujours faire en sorte que la tête tourne un peu de gauche à droite (Spoiler: Math.sin peut être très utile)
- Bonne chance
- Ça va demander de l’organisation mais ça devrait aller
-
@‘jglrxavpok’:
- Il n’y a pas que ça. La partie avec les vecteurs est super importante, entity.canBeSeen vérifie juste que 'y a pas de blocs entre les deux.
- Oui, mais tu peux toujours faire en sorte que la tête tourne un peu de gauche à droite (Spoiler: Math.sin peut être très utile)
- Bonne chance
- Ça va demander de l’organisation mais ça devrait aller
Par contre Entity.class ne prend pas du tout en charge la rotation de la tête. Donc une dernière question avant de commencer : à quoi correspondent les valeurs rotationYaw et rotationPitch ? Je me doute que c’est un repère (x,y) spécifique à l’entité mais lequel correspond à x et lequel à z ?
-
Yaw c’est pour gauche-droite si je me rappelle bien et Pitch pour haut-bas
-
@‘jglrxavpok’:
Yaw c’est pour gauche-droite si je me rappelle bien et Pitch pour haut-bas
Super merci ! Donc x= yaw et y= pitch. Je m’y mets
J’ai un petit problème ^^. Déjà, avec le renderLiving, ça ne colle plus. Donc j’ai mis un extends Render. Le problème c’est que ça ne rend pas du tout, ma tourelle est invisible. J’ai sûrement fait de mauvaises manips mais les variables sont tellement explicites aussi… Var1, var2, var3, var4…
package fr.wirestone.render; import net.minecraft.client.model.ModelBase; import net.minecraft.client.renderer.entity.Render; import net.minecraft.entity.Entity; import net.minecraft.util.ResourceLocation; import fr.wirestone.entity.EntityTurret; public class RenderWirestoneMod extends Render{ public final ResourceLocation texture = new ResourceLocation("wsmod", "textures/entity/Turret.png"); private final ModelBase model; public RenderWirestoneMod(ModelBase model, float shadow){ super(); this.model = model; } @Override protected ResourceLocation getEntityTexture(Entity entity){ return this.getTurretTexture((EntityTurret)entity); } protected ResourceLocation getTurretTexture(EntityTurret turret){ return this.texture; } @Override public void doRender(Entity var1, double var2, double var4, double var6, float var8, float var9){ this.model.render(var1, (float)var2, (float)var4, (float)var6, var8, var9, 1.0F); } }
Ça et le système pour lier la tourelle au bloc qui ne fonctionne pas non plus… Je pense que je vais faire un système d’UUID personnalisé. Ce sera mieux pour pouvoir récupérer ma tourelle.
EDIT : Je viens de comprendre pourquoi ça ne fonctionne pas ! Parce qu’au moment où la tileEntity se charge depuis le NBT, les entités ne sont pas encore chargées dans le monde. Le plus simple, finalement, est d’identifier la TileEntity grâce à un UUID. Ensuite, lorsque la tourelle est instanciée, la TileEntity est informée par la tourelle que celle-ci est chargée et ladite tourelle lui communique sa propre instance.