---
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<PlayerRef> playerArg;
    private final RequiredArg<String> effectArg;
    private final RequiredArg<Integer> durationArg;

    // Serait défini lors de l'initialisation du plugin
    private Store<EntityStore> store;
    private ComponentAccessor<EntityStore> 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<Void> execute(CommandContext ctx) {
        PlayerRef target = playerArg.get(ctx);
        String effectId = effectArg.get(ctx);
        int duration = durationArg.get(ctx);

        Ref<EntityStore> 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<EntityStore> store,
                        ComponentAccessor<EntityStore> componentAccessor) {
    EntityEffect poison = EntityEffect.getAssetMap().getAsset("poison");

    Ref<EntityStore> 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<EntityStore> store,
                                  ComponentAccessor<EntityStore> componentAccessor) {
    EntityEffect invuln = EntityEffect.getAssetMap().getAsset("invulnerability");

    Ref<EntityStore> 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<EntityStore> store,
                            ComponentAccessor<EntityStore> componentAccessor) {
    Ref<EntityStore> 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<EntityStore> store,
                           ComponentAccessor<EntityStore> componentAccessor) {
    Ref<EntityStore> 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 >}}
