--- title: Effets d'Entité type: docs weight: 3 --- Les effets d'entité sont des effets de statut qui peuvent inclure des composants visuels, des modificateurs de stats et des comportements basés sur la durée. ## Configuration EntityEffect ```java public class EntityEffect { protected String id; protected String name; // Clé de localisation protected ApplicationEffects applicationEffects; // Effets visuels/audio protected String modelChange; // Changer le modèle de l'entité protected float duration; // Durée par défaut (secondes) protected boolean infinite; // N'expire jamais ? protected boolean debuff; // Est un effet négatif ? protected String statusEffectIcon; // Icône UI // Dégâts et stats protected Int2FloatMap entityStats; // Modificateurs de stats protected ValueType valueType; // Absolute ou Percent // Comportement protected OverlapBehavior overlapBehavior; // EXTEND, OVERWRITE, IGNORE protected RemovalBehavior removalBehavior; // COMPLETE, DURATION, INFINITE protected boolean invulnerable; // Accorder l'invulnérabilité } ``` ## Accéder aux Assets d'Effets ```java // Obtenir un effet par ID EntityEffect effect = EntityEffect.getAssetMap().getAsset("fire_resistance"); // Obtenir l'index de l'effet pour les opérations int effectIndex = EntityEffect.getAssetMap().getIndex(effect.getId()); ``` ## EffectControllerComponent Le `EffectControllerComponent` gère les effets actifs sur une entité : ```java import com.hypixel.hytale.server.core.entity.effect.EffectControllerComponent; // Obtenir le contrôleur d'effets de l'entité EffectControllerComponent controller = store.getComponent( entityRef, EffectControllerComponent.getComponentType() ); ``` ## Ajouter des Effets ### Ajout Basique ```java EntityEffect effect = EntityEffect.getAssetMap().getAsset("speed_boost"); // Ajouter avec les paramètres par défaut controller.addEffect( entityRef, effect, componentAccessor ); ``` ### Avec Durée Personnalisée ```java // Ajouter avec durée personnalisée et comportement de superposition controller.addEffect( entityRef, effect, 100.0f, // Durée en secondes OverlapBehavior.EXTEND, // Comment gérer la superposition componentAccessor ); ``` ### Effets Infinis ```java // Ajouter un effet qui n'expire jamais controller.addInfiniteEffect( entityRef, EntityEffect.getAssetMap().getIndex(effect.getId()), effect, componentAccessor ); ``` ## Supprimer des Effets ```java // Supprimer un effet spécifique controller.removeEffect( entityRef, EntityEffect.getAssetMap().getIndex(effect.getId()), componentAccessor ); ``` ## Comportements de Superposition ```java public enum OverlapBehavior { EXTEND, // Ajouter la durée à l'effet existant OVERWRITE, // Remplacer l'effet existant IGNORE // Ne pas appliquer si déjà actif } ``` ### Exemples d'Utilisation ```java // Étendre la durée si déjà appliqué controller.addEffect( entityRef, effect, 30.0f, OverlapBehavior.EXTEND, componentAccessor ); // Remplacer avec une durée fraîche controller.addEffect( entityRef, effect, 30.0f, OverlapBehavior.OVERWRITE, componentAccessor ); // Appliquer seulement si pas déjà actif controller.addEffect( entityRef, effect, 30.0f, OverlapBehavior.IGNORE, componentAccessor ); ``` ## Comportements de Suppression ```java public enum RemovalBehavior { COMPLETE, // Supprimer quand terminé DURATION, // Supprimer après la durée INFINITE // Ne jamais supprimer automatiquement } ``` ## Types de Valeurs pour les Stats ```java public enum ValueType { Absolute, // Ajouter/soustraire une valeur fixe Percent // Multiplier par un pourcentage } ``` ## Exemples Pratiques ### Buff par Commande ```java public class BuffCommand extends AbstractCommand { private final RequiredArg playerArg; private final RequiredArg effectArg; private final RequiredArg durationArg; // Serait défini lors de l'initialisation du plugin private Store store; private ComponentAccessor componentAccessor; public BuffCommand() { super("buff", "effects.command.buff.description"); this.playerArg = withRequiredArg("player", "Joueur cible", ArgTypes.PLAYER_REF); this.effectArg = withRequiredArg("effect", "ID de l'effet", ArgTypes.STRING); this.durationArg = withRequiredArg("duration", "Durée en secondes", ArgTypes.INTEGER); } @Override protected CompletableFuture execute(CommandContext ctx) { PlayerRef target = playerArg.get(ctx); String effectId = effectArg.get(ctx); int duration = durationArg.get(ctx); Ref entityRef = target.getReference(); if (entityRef == null || !entityRef.isValid()) { ctx.sender().sendMessage(Message.raw("Joueur non trouvé")); return null; } EntityEffect effect = EntityEffect.getAssetMap().getAsset(effectId); if (effect == null) { ctx.sender().sendMessage(Message.raw("Effet inconnu : " + effectId)); return null; } EffectControllerComponent controller = store.getComponent( entityRef, EffectControllerComponent.getComponentType() ); if (controller != null) { controller.addEffect( entityRef, effect, (float) duration, OverlapBehavior.EXTEND, componentAccessor ); } ctx.sender().sendMessage(Message.raw("Appliqué " + effectId + " à " + target.getUsername())); return null; } } ``` {{< callout type="warning" >}} **Notes API :** - Utilisez `withRequiredArg()` pour définir les arguments, pas `addArgument()` - Utilisez `arg.get(ctx)` pour récupérer les valeurs, pas `ctx.getArg()` - Utilisez `ctx.sender()` pas `ctx.getSender()` - Utilisez `target.getUsername()` pas `target.getName()` - Utilisez `target.getReference()` pour obtenir la référence d'entité (PlayerRef n'a pas `getPlayer()`) {{< /callout >}} ### Effet de Dégâts dans le Temps ```java public void applyPoison(Player player, float duration, Store store, ComponentAccessor componentAccessor) { EntityEffect poison = EntityEffect.getAssetMap().getAsset("poison"); Ref entityRef = player.getReference(); EffectControllerComponent controller = store.getComponent( entityRef, EffectControllerComponent.getComponentType() ); if (controller != null && poison != null) { controller.addEffect( entityRef, poison, duration, OverlapBehavior.EXTEND, componentAccessor ); } player.sendMessage(Message.raw("Vous avez été empoisonné !")); } ``` ### Invulnérabilité Temporaire ```java public void grantInvulnerability(Player player, float seconds, Store store, ComponentAccessor componentAccessor) { EntityEffect invuln = EntityEffect.getAssetMap().getAsset("invulnerability"); Ref entityRef = player.getReference(); EffectControllerComponent controller = store.getComponent( entityRef, EffectControllerComponent.getComponentType() ); if (controller != null && invuln != null) { controller.addEffect( entityRef, invuln, seconds, OverlapBehavior.OVERWRITE, // Durée fraîche componentAccessor ); } } ``` ### Effacer Tous les Effets ```java public void clearAllEffects(Player player, Store store, ComponentAccessor componentAccessor) { Ref entityRef = player.getReference(); EffectControllerComponent controller = store.getComponent( entityRef, EffectControllerComponent.getComponentType() ); if (controller != null) { // Utiliser la méthode clearEffects intégrée controller.clearEffects( entityRef, componentAccessor ); } player.sendMessage(Message.raw("Tous les effets effacés !")); } ``` ## Combiner avec d'Autres Effets Les effets d'entité fonctionnent bien avec les particules et les lumières dynamiques : ```java public void applyMagicBuff(Player player, Store store, ComponentAccessor componentAccessor) { Ref entityRef = player.getReference(); // Appliquer l'effet de statut EntityEffect buff = EntityEffect.getAssetMap().getAsset("magic_power"); EffectControllerComponent controller = store.getComponent( entityRef, EffectControllerComponent.getComponentType() ); if (controller != null && buff != null) { controller.addEffect(entityRef, buff, componentAccessor); } // Ajouter une lueur visuelle ColorLight glow = new ColorLight((byte) 10, (byte) 200, (byte) 50, (byte) 255); DynamicLight light = new DynamicLight(glow); componentAccessor.putComponent( entityRef, DynamicLight.getComponentType(), light ); // Obtenir la position via TransformComponent pour les particules TransformComponent transform = store.getComponent(entityRef, TransformComponent.getComponentType()); if (transform != null) { ParticleUtil.spawnParticleEffect( "magic_aura", transform.getPosition(), componentAccessor ); } } ``` {{< callout type="info" >}} **Note :** Utilisez `player.getReference()` pour obtenir la référence d'entité. La position doit être obtenue via `TransformComponent`, pas directement depuis Player. {{< /callout >}} ## Bonnes Pratiques {{< callout type="info" >}} **Directives pour les Effets :** - Utilisez `EXTEND` pour les buffs cumulables afin de récompenser l'application répétée - Utilisez `OVERWRITE` pour les effets qui doivent réinitialiser leur durée - Utilisez `IGNORE` pour empêcher l'empilement d'effets quand indésirable - Vérifiez toujours si l'effet existe avant de l'appliquer - Considérez les performances avec de nombreux effets simultanés {{< /callout >}}