---
title: Entity Effects
type: docs
weight: 3
---

Entity effects are status effects that can include visual components, stat modifiers, and duration-based behaviors.

## EntityEffect Configuration

```java
public class EntityEffect {
    protected String id;
    protected String name;                      // Localization key

    protected ApplicationEffects applicationEffects;  // Visual/audio effects

    protected String modelChange;               // Change entity model
    protected float duration;                   // Default duration (seconds)

    protected boolean infinite;                 // Never expires?
    protected boolean debuff;                   // Is a negative effect?
    protected String statusEffectIcon;          // UI icon

    // Damage and stats
    protected Int2FloatMap entityStats;         // Stat modifiers
    protected ValueType valueType;              // Absolute or Percent

    // Behavior
    protected OverlapBehavior overlapBehavior;  // EXTEND, OVERWRITE, IGNORE
    protected RemovalBehavior removalBehavior;  // COMPLETE, DURATION, INFINITE

    protected boolean invulnerable;             // Grant invulnerability
}
```

## Accessing Effect Assets

```java
// Get effect by ID
EntityEffect effect = EntityEffect.getAssetMap().getAsset("fire_resistance");

// Get effect index for operations
int effectIndex = EntityEffect.getAssetMap().getIndex(effect.getId());
```

## EffectControllerComponent

The `EffectControllerComponent` manages active effects on an entity:

```java
import com.hypixel.hytale.server.core.entity.effect.EffectControllerComponent;

// Get effect controller from entity
EffectControllerComponent controller = store.getComponent(
    entityRef,
    EffectControllerComponent.getComponentType()
);
```

## Adding Effects

### Basic Addition

```java
EntityEffect effect = EntityEffect.getAssetMap().getAsset("speed_boost");

// Add with default parameters
controller.addEffect(
    entityRef,
    effect,
    componentAccessor
);
```

### With Custom Duration

```java
// Add with custom duration and overlap behavior
controller.addEffect(
    entityRef,
    effect,
    100.0f,                      // Duration in seconds
    OverlapBehavior.EXTEND,      // How to handle overlap
    componentAccessor
);
```

### Infinite Effects

```java
// Add an effect that never expires
controller.addInfiniteEffect(
    entityRef,
    EntityEffect.getAssetMap().getIndex(effect.getId()),
    effect,
    componentAccessor
);
```

## Removing Effects

```java
// Remove specific effect
controller.removeEffect(
    entityRef,
    EntityEffect.getAssetMap().getIndex(effect.getId()),
    componentAccessor
);
```

## Overlap Behaviors

```java
public enum OverlapBehavior {
    EXTEND,     // Add duration to existing effect
    OVERWRITE,  // Replace existing effect
    IGNORE      // Don't apply if already active
}
```

### Usage Examples

```java
// Extend duration if already applied
controller.addEffect(
    entityRef,
    effect,
    30.0f,
    OverlapBehavior.EXTEND,
    componentAccessor
);

// Replace with fresh duration
controller.addEffect(
    entityRef,
    effect,
    30.0f,
    OverlapBehavior.OVERWRITE,
    componentAccessor
);

// Only apply if not already active
controller.addEffect(
    entityRef,
    effect,
    30.0f,
    OverlapBehavior.IGNORE,
    componentAccessor
);
```

## Removal Behaviors

```java
public enum RemovalBehavior {
    COMPLETE,   // Remove when complete
    DURATION,   // Remove after duration
    INFINITE    // Never remove automatically
}
```

## Value Types for Stats

```java
public enum ValueType {
    Absolute,   // Add/subtract flat value
    Percent     // Multiply by percentage
}
```

## Practical Examples

### Buff on Command

```java
public class BuffCommand extends AbstractCommand {
    private final RequiredArg<PlayerRef> playerArg;
    private final RequiredArg<String> effectArg;
    private final RequiredArg<Integer> durationArg;

    // Would be set during plugin initialization
    private Store<EntityStore> store;
    private ComponentAccessor<EntityStore> componentAccessor;

    public BuffCommand() {
        super("buff", "effects.command.buff.description");
        this.playerArg = withRequiredArg("player", "Target player", ArgTypes.PLAYER_REF);
        this.effectArg = withRequiredArg("effect", "Effect ID", ArgTypes.STRING);
        this.durationArg = withRequiredArg("duration", "Duration in seconds", 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("Player not found"));
            return null;
        }

        EntityEffect effect = EntityEffect.getAssetMap().getAsset(effectId);
        if (effect == null) {
            ctx.sender().sendMessage(Message.raw("Unknown effect: " + 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("Applied " + effectId + " to " + target.getUsername()));
        return null;
    }
}
```

{{< callout type="warning" >}}
**API Notes:**
- Use `withRequiredArg()` to define arguments, not `addArgument()`
- Use `arg.get(ctx)` to retrieve values, not `ctx.getArg()`
- Use `ctx.sender()` not `ctx.getSender()`
- Use `target.getUsername()` not `target.getName()`
- Use `target.getReference()` to get entity reference (PlayerRef doesn't have `getPlayer()`)
{{< /callout >}}

### Damage Over Time Effect

```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("You have been poisoned!"));
}
```

### Temporary Invulnerability

```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,  // Fresh duration
            componentAccessor
        );
    }
}
```

### Clear All Effects

```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) {
        // Use the built-in clearEffects method
        controller.clearEffects(
            entityRef,
            componentAccessor
        );
    }

    player.sendMessage(Message.raw("All effects cleared!"));
}
```

## Combining with Other Effects

Entity effects work well with particles and dynamic lights:

```java
public void applyMagicBuff(Player player, Store<EntityStore> store,
                           ComponentAccessor<EntityStore> componentAccessor) {
    Ref<EntityStore> entityRef = player.getReference();

    // Apply status effect
    EntityEffect buff = EntityEffect.getAssetMap().getAsset("magic_power");
    EffectControllerComponent controller = store.getComponent(
        entityRef,
        EffectControllerComponent.getComponentType()
    );
    if (controller != null && buff != null) {
        controller.addEffect(entityRef, buff, componentAccessor);
    }

    // Add visual glow
    ColorLight glow = new ColorLight((byte) 10, (byte) 200, (byte) 50, (byte) 255);
    DynamicLight light = new DynamicLight(glow);
    componentAccessor.putComponent(
        entityRef,
        DynamicLight.getComponentType(),
        light
    );

    // Get position from TransformComponent for particle spawn
    TransformComponent transform = store.getComponent(entityRef, TransformComponent.getComponentType());
    if (transform != null) {
        ParticleUtil.spawnParticleEffect(
            "magic_aura",
            transform.getPosition(),
            componentAccessor
        );
    }
}
```

{{< callout type="info" >}}
**Note:** Use `player.getReference()` to get the entity reference. Position must be obtained from `TransformComponent`, not directly from Player.
{{< /callout >}}

## Best Practices

{{< callout type="info" >}}
**Effect Guidelines:**
- Use `EXTEND` for stackable buffs to reward repeated application
- Use `OVERWRITE` for effects that should reset duration
- Use `IGNORE` to prevent effect stacking when undesired
- Always check if effect exists before applying
- Consider performance with many simultaneous effects
{{< /callout >}}
