370 lines
10 KiB
Markdown
370 lines
10 KiB
Markdown
---
|
|
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 >}}
|