HyCodeYourTale

Effects & Buffs

Effects & Buffs

Dokumentace k efektům a buffům v Hytale.

Obsah

| Soubor | Popis |
|--------|-------|
| EFFECT_TYPES.md | EntityEffect, ActiveEntityEffect, OverlapBehavior, RemovalBehavior |
| APPLYING_EFFECTS.md | EffectControllerComponent, aplikace a odebrání efektů |

---

Přehled

Efekty jsou spravovány přes EffectControllerComponent - ECS komponentu která drží aktivní efekty na entitě.

---

EffectControllerComponent

Z dekompilovaného kódu - komponenta pro správu efektů:

// Získání effect controlleru
EffectControllerComponent effects = store.getComponent(
ref,
EffectControllerComponent.getComponentType()
);

if (effects != null) {
// Práce s efekty
}

---

Typy Efektů (Koncept)

| Kategorie | Příklady |
|-----------|----------|
| Buff | Speed, Strength, Resistance |
| Debuff | Slowness, Weakness, Poison |
| Neutral | Invisibility, Night Vision |
| Special | Fire, Freezing |

---

Aplikace Efektu

public void applyEffect(Player player, String effectId, int duration, int level) {
World world = player.getWorld();

world.execute(() -> {
Ref ref = player.getRef();
Store store = ref.getStore();

EffectControllerComponent effects = store.getComponent(
ref,
EffectControllerComponent.getComponentType()
);

if (effects != null) {
// Aplikuj efekt
// effects.addEffect(effectId, duration, level);
}
});
}

---

Odebrání Efektu

public void removeEffect(Player player, String effectId) {
World world = player.getWorld();

world.execute(() -> {
Ref ref = player.getRef();
Store store = ref.getStore();

EffectControllerComponent effects = store.getComponent(
ref,
EffectControllerComponent.getComponentType()
);

if (effects != null) {
// Odeber efekt
// effects.removeEffect(effectId);
}
});
}

---

Kontrola Aktivního Efektu

public boolean hasEffect(Player player, String effectId) {
Ref ref = player.getRef();
Store store = ref.getStore();

EffectControllerComponent effects = store.getComponent(
ref,
EffectControllerComponent.getComponentType()
);

if (effects != null) {
// return effects.hasEffect(effectId);
}

return false;
}

---

Effect Definice (Assets)

Efekty mohou být definovány v assets:

{
"Id": "speed",
"Name": "Speed",
"Type": "Buff",
"Icon": "effect_speed.png",
"Color": "#7CAFC2",
"Modifiers": [
{
"Attribute": "MovementSpeed",
"Operation": "Multiply",
"ValuePerLevel": 0.2
}
],
"Particles": "speed_particles",
"Sound": "effect_applied"
}

---

Vizuální Efekty

ComponentUpdateType

Z dekompilovaného kódu:

| Typ | Popis |
|-----|-------|
| EntityEffects | Aktivní efekty na entitě |
| DynamicLight | Dynamické osvětlení |
| ActiveAnimations | Aktivní animace |

---

Příkaz pro Efekty

public class EffectCommand extends AbstractPlayerCommand {

private final RequiredArg effectArg =
withRequiredArg("effect", "desc", ArgTypes.STRING);

private final DefaultArg durationArg =
withDefaultArg("duration", "desc", ArgTypes.INTEGER, 30, "30");

private final DefaultArg levelArg =
withDefaultArg("level", "desc", ArgTypes.INTEGER, 1, "1");

public EffectCommand() {
super("effect", "myplugin.commands.effect.desc");
requirePermission(HytalePermissions.of("myplugin.effect"));
}

@Override
protected void execute(CommandContext context, Store store,
Ref ref, PlayerRef playerRef, World world) {

String effectId = effectArg.get(context);
int duration = durationArg.get(context);
int level = levelArg.get(context);

// Aplikuj efekt
applyEffect(ref, store, effectId, duration, level);

context.sendMessage(
Message.raw("Aplikován efekt: " + effectId +
" (level " + level + ", " + duration + "s)")
);
}

private void applyEffect(Ref ref, Store store,
String effectId, int duration, int level) {
EffectControllerComponent effects = store.getComponent(
ref,
EffectControllerComponent.getComponentType()
);

if (effects != null) {
// effects.addEffect(effectId, duration * 20, level); // ticks
}
}
}

---

Knockback

KnockbackComponent

// Knockback je komponenta pro fyziku odhození
KnockbackComponent knockback = store.getComponent(
ref,
KnockbackComponent.getComponentType()
);

---

Movement States

MovementStatesComponent

// Stav pohybu entity (běh, chůze, plavání, létání...)
MovementStatesComponent movement = store.getComponent(
ref,
MovementStatesComponent.getComponentType()
);

---

Vlastní Effect Systém

Pokud potřebuješ vlastní effect systém:

public class CustomEffect implements Component {
private final String effectId;
private final long startTime;
private final int duration; // v tickech
private final int level;

public CustomEffect(String effectId, int duration, int level) {
this.effectId = effectId;
this.startTime = System.currentTimeMillis();
this.duration = duration;
this.level = level;
}

public boolean isExpired() {
long elapsed = System.currentTimeMillis() - startTime;
return elapsed >= (duration * 50); // 50ms per tick
}

public String getEffectId() { return effectId; }
public int getLevel() { return level; }

@Override
public Component clone() {
return new CustomEffect(effectId, duration, level);
}
}

Effect Manager

public class EffectManager {

private final Map> playerEffects = new ConcurrentHashMap<>();

public void addEffect(UUID playerId, String effectId, int duration, int level) {
playerEffects.computeIfAbsent(playerId, k -> new CopyOnWriteArrayList<>())
.add(new CustomEffect(effectId, duration, level));
}

public void removeExpiredEffects() {
for (List effects : playerEffects.values()) {
effects.removeIf(CustomEffect::isExpired);
}
}

public boolean hasEffect(UUID playerId, String effectId) {
List effects = playerEffects.get(playerId);
if (effects == null) return false;

return effects.stream()
.anyMatch(e -> e.getEffectId().equals(effectId) && !e.isExpired());
}
}

---

Shrnutí

| Komponenta | Popis |
|------------|-------|
| EffectControllerComponent | Správa efektů |
| KnockbackComponent | Knockback fyzika |
| MovementStatesComponent | Stav pohybu |

| Operace | Poznámka |
|---------|----------|
| Přidání efektu | Přes EffectControllerComponent |
| Odebrání efektu | Přes EffectControllerComponent |
| Kontrola efektu | Přes EffectControllerComponent |
| Vlastní systém | Implementuj vlastní Component |

Last updated: 20. ledna 2026