Appearance
Implementation d'un effet
- Introduction aux Effets de Statut (Mob Effects)
Dans Minecraft, les effets de statut (historiquement appelés Potion Effects et nommés MobEffect dans le code moderne) représentent des altérations d'état appliquées à une entité vivante (joueur, monstre, animal). Ces effets peuvent être bénéfiques (Vitesse, Force, Régénération) ou néfastes (Poison, Lenteur, Faiblesse).
Ce cours détaille comment, à travers l'API de Forge pour la version 1.20.1, vous pouvez associer ces effets à vos propres objets (Items). Nous étudierons les deux grandes approches possibles:
L'approche passive / alimentaire : L'effet est configuré directement lors de la création de l'item (ex : manger une pomme magique donne un effet).
L'approche active / événementielle : L'effet est déclenché par une action précise via le code (ex : frapper un ennemi avec une épée lui applique du poison, ou porter une armure complète confère une résistance).
Concepts clés à retenir :
MobEffect: La nature même de l'effet (ex :MobEffects.POISON). C'est un objet unique de type Singleton enregistré par le jeu.MobEffectInstance: L'application concrète de cet effet sur une entité. Elle contient les variables dynamiques comme la durée et la puissance (amplificateur).
- L'anatomie d'une instance d'effet (
MobEffectInstance)
Pour appliquer un effet, vous devez instancier la classe MobEffectInstance. Son constructeur le plus classique prend trois paramètres principaux:
java
new MobEffectInstance(MobEffect effect, int duration, int amplifier); [cite_start]// [cite: 790]effect: L'effet choisi issu de la classe de référencenet.minecraft.world.effect.MobEffects.duration: La durée de l'effet exprimée en Ticks. Dans Minecraft, 1 seconde = 20 ticks. Pour calculer une durée en secondes, multipliez la valeur par 20 (ex : 10 secondes = 10 x 20 = 200 ticks.amplifier: Le niveau ou la puissance de l'effet. Attention, l'indexation commence à 0. Ainsi, un amplificateur de 0 correspond à l'effet de niveau I (ex : Vitesse I), et un amplificateur de 1 correspond au niveau II (ex : Vitesse II).
- Méthode 1 : Ajouter des effets via la configuration alimentaire (
FoodProperties)
C'est la méthode la plus simple pour l'implémentation sur un consommable (nourriture ou potion personnalisée). Elle s'exécute directement dans la classe d'enregistrement de vos objets sans nécessiter de classe personnalisée.
Exemple d'enregistrement d'un aliment à effets:
java
[cite_start]public static final RegistryObject<Item> MAGIC_APPLE = ITEMS.register("magic_apple", // [cite: 802]
() [cite_start]-> new Item(new Item.Properties().food( // [cite: 802]
[cite_start]new FoodProperties.Builder() // [cite: 803]
[cite_start].nutrition(4) // Restaure 2 gigots [cite: 804]
[cite_start].saturationMod(0.3f) // [cite: 804]
[cite_start]// Format : Effet, Durée (Ticks), Amplificateur, Probabilité (1.0f = 100%) [cite: 805, 806]
[cite_start].effect(() -> new MobEffectInstance(MobEffects.REGENERATION, 200, 1), 1.0f) // [cite: 807]
[cite_start].effect(() -> new MobEffectInstance(MobEffects.DAMAGE_RESISTANCE, 600, 0), 0.5f) // 50% de chance [cite: 807, 808]
[cite_start].alwaysEat() // Permet de consommer l'item même si la barre de faim est pleine [cite: 809]
[cite_start].build() // [cite: 809]
[cite_start])) // [cite: 810]
); [cite_start]// [cite: 811]Attention au format
Supplieren 1.20.1 ! Dans les versions récentes de Forge comme la 1.20.1, la méthodeeffect()du constructeur de nourriture requiert l'utilisation d'unSupplier(représenté par la syntaxe lambda() ->). Cela évite le chargement prématuré des classes d'effets lors de l'initialisation du jeu.
- Méthode 2 : Appliquer des effets lors d'une action active (Épée, Outil)
Si vous souhaitez qu'un effet s'apply lorsqu'un joueur frappe une entité avec une arme spécifique, vous devez créer une classe personnalisée pour votre Item et hériter de la classe parente appropriée (comme SwordItem). Vous devez ensuite surcharger (override) la méthode hurtEnemy.
Code de l'item personnalisé (ex : Épée empoisonnée):
java
package com.monmod.item; [cite_start]// [cite: 819]
import net.minecraft.world.effect.MobEffectInstance; [cite_start]// [cite: 820]
import net.minecraft.world.effect.MobEffects; [cite_start]// [cite: 820]
import net.minecraft.world.entity.LivingEntity; [cite_start]// [cite: 821]
import net.minecraft.world.item.ItemStack; [cite_start]// [cite: 821]
import net.minecraft.world.item.SwordItem; [cite_start]// [cite: 821]
import net.minecraft.world.item.Tier; [cite_start]// [cite: 822]
[cite_start]public class PoisonSwordItem extends SwordItem { // [cite: 823]
[cite_start]public PoisonSwordItem(Tier tier, int attackDamage, float attackSpeed, Properties properties) { // [cite: 824, 827]
super(tier, attackDamage, attackSpeed, properties); [cite_start]// [cite: 830]
}
[cite_start]@Override // [cite: 831]
[cite_start]public boolean hurtEnemy(ItemStack stack, LivingEntity target, LivingEntity attacker) { // [cite: 832]
// Applique l'effet Poison II (amplifier: 1) pendant 5 secondes (100 ticks) sur la cible
target.addEffect(new MobEffectInstance(MobEffects.POISON, 100, 1)); [cite_start]// [cite: 833]
// Applique l'effet Vitesse I (amplifier: 0) pendant 3 secondes (60 ticks) sur l'attaquant
attacker.addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SPEED, 60, 0)); [cite_start]// [cite: 834]
return super.hurtEnemy(stack, target, attacker); [cite_start]// [cite: 835]
[cite_start]} // [cite: 836]
}- Méthode 3 : Effets passifs continus (Armures complètes)
Pour créer une armure qui octroie des bonus permanents tant qu'elle est portée en totalité, vous devez surcharger la méthode onArmorTick dans votre classe d'armure personnalisée héritant de ArmorItem.
Code de l'armure personnalisée:
java
package com.monmod.item; [cite_start]// [cite: 841]
import net.minecraft.world.effect.MobEffectInstance; [cite_start]// [cite: 842]
import net.minecraft.world.effect.MobEffects; [cite_start]// [cite: 843]
import net.minecraft.world.entity.player.Player; [cite_start]// [cite: 844]
import net.minecraft.world.item.ArmorItem; [cite_start]// [cite: 845]
import net.minecraft.world.item.ArmorMaterial; [cite_start]// [cite: 846]
import net.minecraft.world.item.ItemStack; [cite_start]// [cite: 847]
import net.minecraft.world.level.Level; [cite_start]// [cite: 848]
import com.monmod.registry.ModItems; [cite_start]// Vos items enregistrés [cite: 849]
[cite_start]public class CustomArmorItem extends ArmorItem { // [cite: 850]
[cite_start]public CustomArmorItem(ArmorMaterial material, Type type, Properties properties) { // [cite: 851]
super(material, type, properties); [cite_start]// [cite: 851]
[cite_start]} // [cite: 852]
[cite_start]@Override // [cite: 853]
[cite_start]public void onArmorTick(ItemStack stack, Level level, Player player) { // [cite: 854]
[cite_start]// Pour éviter les calculs superflus, on ne vérifie qu'une fois (via les bottes par exemple) [cite: 855]
[cite_start]if (!level.isClientSide() && stack.getItem() == ModItems.CUSTOM_BOOTS.get()) { // [cite: 856]
[cite_start]if (hasFullSetOfArmor(player)) { // [cite: 856]
// Donne l'effet Résistance au feu I. Durée de 260 ticks (13s) pour éviter le clignotement
player.addEffect(new MobEffectInstance(MobEffects.FIRE_RESISTANCE, 260, 0, false, false, true)); [cite_start]// [cite: 857, 858]
}
}
[cite_start]} // [cite: 861]
[cite_start]private boolean hasFullSetOfArmor(Player player) { // [cite: 864]
ItemStack boots = player.getInventory().getArmor(0); [cite_start]// [cite: 865, 866]
ItemStack leggings = player.getInventory().getArmor(1); [cite_start]// [cite: 867, 868]
ItemStack chestplate = player.getInventory().getArmor(2); [cite_start]// [cite: 869, 870]
ItemStack helmet = player.getInventory().getArmor(3); [cite_start]// [cite: 871]
[cite_start]return !boots.isEmpty() && !leggings.isEmpty() && !chestplate.isEmpty() && !helmet.isEmpty() // [cite: 872, 873]
[cite_start]&& boots.getItem() == ModItems.CUSTOM_BOOTS.get() // [cite: 874]
[cite_start]&& leggings.getItem() == ModItems.CUSTOM_LEGGINGS.get() // [cite: 875]
[cite_start]&& chestplate.getItem() == ModItems.CUSTOM_CHESTPLATE.get() // [cite: 876]
&& helmet.getItem() == ModItems.CUSTOM_HELMET.get(); [cite_start]// [cite: 877]
}
}Astuce avancée pour les effets passifs : Le constructeur étendu
Dans le code de l'armure ci-dessus, nous utilisons un constructeur étendu de MobEffectInstance:
new MobEffectInstance(effet, duree, amplificateur, ambient, visibleParticles, showIcon)
En passant false, false, true aux trois derniers paramètres, nous masquons les particules à l'écran pour que le joueur ne soit pas gêné visuellement tout en gardant l'icône active dans l'inventaire.
- Liste de référence des principaux
MobEffectsnatifs
Voici les identifiants techniques des principaux effets que vous pouvez appeler directement depuis la classe net.minecraft.world.effect.MobEffects:
| Nom en jeu | Référence Java (Champ static) | Type d'effet |
|---|---|---|
| Vitesse | MobEffects.MOVEMENT_SPEED | Bénéfique |
| Lenteur | MobEffects.MOVEMENT_SLOWDOWN | Néfaste |
| Force | MobEffects.DAMAGE_BOOST | Bénéfique |
| Saut amélioré | MobEffects.JUMP | Bénéfique |
| Régénération | MobEffects.REGENERATION | Bénéfique |
| Résistance | MobEffects.DAMAGE_RESISTANCE | Bénéfique |
| Résistance au feu | MobEffects.FIRE_RESISTANCE | Bénéfique |
| Apnée / Respiration | MobEffects.WATER_BREATHING | Bénéfique |
| Invisibilité | MobEffects.INVISIBILITY | Bénéfique |
| Poison | MobEffects.POISON | Néfaste |
| Wither | MobEffects.WITHER | Néfaste |
| Nyctalopie (Vision de nuit) | MobEffects.NIGHT_VISION | Bénéfique |
| Satiété | MobEffects.SATURATION | Bénéfique |
| Lévitation | MobEffects.LEVITATION | Néfaste |
Exercices pratiques proposés
Le piment de feu : Créez un item consommable de type nourriture qui, lorsqu'il est mangé, confère l'effet
FIRE_RESISTANCEpendant 30 secondes, mais applique également l'effetMOVEMENT_SPEEDde niveau II pendant 10 secondes.La dague de ralentissement : Créez une arme personnalisée qui applique l'effet
MOVEMENT_SLOWDOWNde niveau III pendant seulement 3 secondes à chaque fois qu'une entité est touchée.