Faire un enchantement



  • Sommaire

    Introduction

    Bonjour tout le monde, aujourd'hui dans ce (petit) tuto, nous allons voir comment créer notre propre enchantement et lui ajouter des effets !
    Pour ce tutoriel, nous allons réaliser un enchantement qui permet d'empoisonner l'entité touchée pendant 15 secondes.

    Pré-requis

    Code

    Les classes essentielles :

    Pour ce tutoriel, nous aurons besoins de 3 classes: La classe principale, la classe de l'enchantement et la classe qui gère les évènements de forge.

    Pour commencer, allez dans votre classe principale, et déclarez une variable de type Enchantment que je nommerais enchantTuto (N'oubliez pas d'importer la classe net.minecraft.enchantment.Enchantment).

    Cela devrait donner quelque chose comme ci-dessous :

    public static Enchantment enchantTuto;
    

    Rendez-vous ensuite dans la méthode preInit() de votre classe principale, celle qui prend en paramètre un FMLPreInitializationEvent, et initialisez votre enchantement comme ceci :

    @EventHandler
    public void preInit(FMLPreInitializationEvent event) {
        enchantTuto = new EnchantmentTuto();
    }
    

    Vous aurez une erreur sur EnchantmentTuto(), pour la corriger, créez une nouvelle classe que vous nommerez... EnchantmentTuto 😄

    Faites la hériter de la classe net.minecraft.enchantment.Enchantment, puis ajoutez un constructeur sans aucun paramètre, comme ceci :

    public class EnchantmentTuto extends Enchantment {
    
        public EnchantmentTuto() {
    
        }
    }
    

    Vous aurez une erreur sur le constructeur, pour y remédier, ajoutez cette ligne de code dans le constructeur :

    super(120, 0, EnumEnchantmentType.weapon);
    

    Explications :

    • le premier int(120) est l'id de l'enchantement, vous pouvez mettre n'importe quelle valeur du moment qu'elle est libre et qu'elle ne dépasse pas 256 ;).

    • le second int(0) est le "weight" de l'enchantement, si vous mettez 0, il n'y aura pas de livre enchanté de ce type dans les coffres générés aléatoirement. (Merci Robin) 😄

    • le 3ème paramètre est un paramètre de type EnumEnchantmentType, pour cet exemple j'ai "weapon" mais j'aurais pu mettre "bow", "armor_boots" ou encore "fishing_rod".

    Et voila, vous avez techniquement fini la classe de votre enchantement, nous reviendrons dans une autre partie pour la "finaliser".

    NB : N'oubliez pas de donner un nom à votre enchantement, pour faire cela, faites comme ceci:

            enchantTuto = new EnchantmentTuto().setName("enchantTuto");
    

    Et voila ! Si vous lancez le jeu, vous aurez normalement votre enchantement sous forme de livre mais malheureusement, pour l'instant, votre enchantement ne fais rien du tout :(. Mais ne vous inquiétez pas, cela ne va pas durer ;).

    Ajouter un effet :

    Pour ajouter un effet (ici empoisonner l'entité touchée), allez dans votre méthode preInit(), et ajoutez cette ligne de code:

            MinecraftForge.EVENT_BUS.register(new ClasseQuiGereLesEnchantements());
    

    où "ClasseQuiGereLesEnchantements" est à remplacer par le nom de votre classe qui... gère les enchantements 😛

    Codez cette fameuse classe, puis créez une méthode qui va gérer les effets de nos enchantements. Nous aurons besoin de savoir quand une entité prend des dégâts. Pour cela nous utiliserons donc un LivingHurtEvent en tant que paramètre, ce qui nous donne :

    @SubscribeEvent
    public void onHurt(LivingHurtEvent event) {
    
    }
    

    (Faites CTRL + Shift + O pour générer tous les imports).

    Examinons cela ligne par ligne :

    • le @SubscribeEvent permet d'indiquer à Forge qu'il doit gérer un évènement dans cette méthode.
    • la méthode onHurt, qui prend en paramètre un LivingHurtEvent, donc qui est appelée à chaque fois qu'une entité prend des dégâts.
      Vous voyez où je veux en venir? Non? On y arrive, ne vous impatientez pas 😉 😛

    Maintenant, commençons à coder notre effet !

    En premier lieu, il faut vérifier si l'entité responsable des dégâts est bien une entité "vivante" (et pas une boule de feu par exemple):

    if (event.source.getEntity() instanceof EntityLivingBase) {
    
    }
    

    Ceci fait, nous pouvons créer une instance de note EntityLivingBase pour raccourcir le futur code 😉

    EntityLivingBase entity = (EntityLivingBase) event.source.getEntity();
    

    Maintenant, il faut vérifier si notre entité possède un objet :

    if (entity.getHeldItem() != null) {
    
    }
    

    Maintenant, nous devons déterminer si cet objet possède notre enchantement, pour ce faire je vous propose de créer une méthode simple qui retourne un booléen, soit true si l'item a l'enchantement, soit false s'il ne l'a pas.

    (Je vous donne directement le code de la méthode en entier)

    public boolean hasEnchantment(ItemStack stack, int id) {
        boolean flag = false;
        if (stack.getEnchantmentTagList() != null) {
            for (int i = 0; i < stack.getEnchantmentTagList().tagCount(); i++) {
                if (stack.getEnchantmentTagList().getCompoundTagAt(i).getShort("id") == id) {
                    flag = true;
                } else {
                    flag = false;
                }
            }
        }
        return flag;
    }
    

    Pour résumer cette petite méthode, elle vérifie si l'itemstack passé en paramètre a un enchantement qui a le même id que celui passé en paramètre. C'est très simple mais très utile 😄

    A partir de là, nous avons presque fini, il suffit juste d'ajouter ceci :

    if (hasEnchantment(entity.getHeldItem(), 120)) {
        event.entityLiving.addPotionEffect(new PotionEffect(Potion.poison.id, 300, 0));
    }
    

    On vérifie s'il y a bien notre enchantement sur l'itemstack puis on ajoute l'effet de potion ! Facile comme tout 😄

    Votre classe entière devrait ressembler à ceci :

    package com.ffmt.tuto.event;
    
    import net.minecraft.entity.EntityLivingBase;
    import net.minecraft.item.ItemStack;
    import net.minecraft.potion.Potion;
    import net.minecraft.potion.PotionEffect;
    import net.minecraftforge.event.entity.living.LivingHurtEvent;
    import cpw.mods.fml.common.eventhandler.SubscribeEvent;
    
    public class EnchantmentHandler {
    
        @SubscribeEvent
        public void onHurt(LivingHurtEvent event) {
            if (event.source.getEntity() instanceof EntityLivingBase) {
                EntityLivingBase entity = (EntityLivingBase) event.source.getEntity();
                if (entity.getHeldItem() != null) {
                    if (hasEnchantment(entity.getHeldItem(), 120)) {
                        event.entityLiving.addPotionEffect(new PotionEffect(Potion.poison.id, 300, 0));
                    }
                }
            }
        }
    
        public boolean hasEnchantment(ItemStack stack, int id) {
            boolean flag = false;
            if (stack.getEnchantmentTagList() != null) {
                for (int i = 0; i < stack.getEnchantmentTagList().tagCount(); i++) {
                    if (stack.getEnchantmentTagList().getCompoundTagAt(i).getShort("id") == id) {
                        flag = true;
                    } else {
                        flag = false;
                    }
                }
            }
            return flag;
        }
    }
    

    Et voila ! Si vous lancez le jeu, vous devriez mettre l'effet poison aux entitées touchées pendant 15 secondes 😄

    Finaliser son enchantement :

    Vous y êtes presque ! Pour finaliser son enchantement, allez dans vos fichier .lang et ajoutez le nom "localisé" de votre enchantement. Par exemple :

    enchantment.enchantTuto=Enchantment Tutorial
    

    Enfin, pour changer le niveau maximum de votre enchantement, rendez-vous dans la classe de l'enchantement et ajoutez ceci :

    public int getMaxLevel() {
            return 3;
    }
    

    Dans cet exemple, le niveau maximal de notre enchantement sera de 3.

    Bonus

    Pour récupérer le niveau d'un enchantement, il suffit d'utiliser cette méthode :

    EnchantmentHelper.getEnchantmentLevel(id, itemstack);
    

    Nous pouvons maintenant customiser la durée de notre effet en fonction du niveau (par exemple), il suffit de faire :

    int level = EnchantmentHelper.getEnchantmentLevel(120, entity.getHeldItem());
    event.entityLiving.addPotionEffect(new PotionEffect(Potion.poison.id, 300 * level, 1 * level));
    

    Et voila ! Ce petit tutoriel est terminé ! J'espère que cela vous aidera ! Si vous trouvez un bug ou vous bloquez quelque part, n'hésitez pas à le dire en commentaire. Sur ce, à bientôt !

    Crédits

    Rédaction :

    Correction :

    Creative Commons
    Ce tutoriel de Minecraft Forge France est mis à disposition selon les termes de la licence Creative Commons Attribution - Pas d’Utilisation Commerciale - Partage dans les Mêmes Conditions 4.0 International

    retourRetour vers le sommaire des tutoriels



  • Bon boulot, je m'occuperais de la correction si ce tuto venait à être validé 😉



  • D'accord, merci beaucoup 😄


  • Administrateurs

    Le "weight" est utilisé dans la probabilité de génération. Certains coffres ont des livres enchantés dedans, bah c'est ça. Donc 0, pas de livre enchanté de ce type dans les coffres
    Visiblement il est aussi utilisé dans l'enclume, mais c'est un gros bordel le code, ça doit surement jouer sur le coût de réparation.



  • Ah d'accord 😄


  • Administrateurs

    Il manque juste les balises aller et ancres pour qu'on puisse directement cliquer sur le menu.


  • Administrateurs

    Je viens de modifier le tutoriel pour appliquer le modèle, il reste à attendre le passage d'un correcteur.



  • Très bon tutoriel 😄 Merci !



  • De rien merci à toi 😄



  • bonjour,j'aimerais faire un enchantement avec les armures mais je n'y arrive pas est ce que quelqu'un pourrait m'aiguiller ? merci 🙂



  • 
    public boolean hasEnchantment(ItemStack stack, int id) {
     boolean flag = false;
     if (stack.getEnchantmentTagList() != null) {
       for (int i = 0; i < stack.getEnchantmentTagList().tagCount(); i++) {
         if (stack.getEnchantmentTagList().getCompoundTagAt(i).getShort("id") == id) {
           flag = true;
         }* else {
           flag = false;
         }*
       }
     }
     return flag;
    }
    

    Je me trompe peut-être mais le "else" est une erreur car s'il y a d'autres enchantements après, la fonction va retourner false, je propose 2 fixes :

    
    public boolean hasEnchantment(ItemStack stack, int id) {
     boolean flag = false;
     if (stack.getEnchantmentTagList() != null) {
       for (int i = 0; i < stack.getEnchantmentTagList().tagCount(); i++) {
         if (stack.getEnchantmentTagList().getCompoundTagAt(i).getShort("id") == id) {
           flag = true;
         }
       }
     }
     return flag;
    }
    

    ou

    
    public boolean hasEnchantment(ItemStack stack, int id) {
     if (stack.getEnchantmentTagList() != null) {
       for (int i = 0; i < stack.getEnchantmentTagList().tagCount(); i++) {
         if (stack.getEnchantmentTagList().getCompoundTagAt(i).getShort("id") == id) {
           return true;
         }
       }
     }
     return false;
    }
    

    (Cette dernière permettrait d'éviter de faire tourner une boucle pour rien)



  • Bonjours, j'ai fais comme le tuto pour creer mon enchantement poison mais l'effet ne se produit que sur les mob et pas les joueur alors que lorsque que j'ai creer un autre enchantement (de soin se coup la) il agit sur toute les entité meme les joueur, voici mon code :

    
    package fairytail.common;
    
    import net.minecraft.enchantment.EnchantmentHelper;
    import net.minecraft.entity.EntityLivingBase;
    import net.minecraft.item.ItemStack;
    import net.minecraft.potion.Potion;
    import net.minecraft.potion.PotionEffect;
    import net.minecraftforge.event.entity.living.LivingHurtEvent;
    import cpw.mods.fml.common.eventhandler.SubscribeEvent;
    
    public class EnchantmentHandler {
    
    @SubscribeEvent
    public void onHurt(LivingHurtEvent event) {
    if (event.source.getEntity() instanceof EntityLivingBase) {
    EntityLivingBase entity = (EntityLivingBase) event.source.getEntity();
    if (entity.getHeldItem() != null) {
    if (hasEnchantment(entity.getHeldItem(), 121)) {
    event.entityLiving.addPotionEffect(new PotionEffect(Potion.heal.id, 1, 1));
    }
    }
    }
    }
    
    public boolean hasEnchantment(ItemStack stack, int id) {
    boolean flag = false;
    if (stack.getEnchantmentTagList() != null) {
    for (int i = 0; i < stack.getEnchantmentTagList().tagCount(); i++) {
    if (stack.getEnchantmentTagList().getCompoundTagAt(i).getShort("id") == id) {
    flag = true;
    } else {
    flag = false;
    }
    }
    }
    return flag;
    }
    
    @SubscribeEvent
    public void onHurt1(LivingHurtEvent event) {
    if (event.source.getEntity() instanceof EntityLivingBase) {
    EntityLivingBase entity = (EntityLivingBase) event.source.getEntity();
    if (entity.getHeldItem() != null) {
    if (hasEnchantment(entity.getHeldItem(), 120)) {
    int level = EnchantmentHelper.getEnchantmentLevel(120, entity.getHeldItem());
    event.entityLiving.addPotionEffect(new PotionEffect(Potion.poison.id, 100 * level, 1));
    }
    }
    }
    
    }
    
    public boolean hasEnchantment1(ItemStack stack, int id) {
    boolean flag = false;
    if (stack.getEnchantmentTagList() != null) {
    for (int i = 0; i < stack.getEnchantmentTagList().tagCount(); i++) {
    if (stack.getEnchantmentTagList().getCompoundTagAt(i).getShort("id") == id) {
    flag = true;
    } else {
    flag = false;
    }
    }
    }
    return flag;
    }
    }