feat: enhance HytaleVfxEmitter to spawn Splash particles and apply tint effects
- Updated HytaleVfxEmitter to emit Splash particles directly using ParticleUtil, ensuring client-side effect deduplication is bypassed. - Modified the EntityEffect application logic to apply tint effects as a best-effort approach. - Adjusted the Chain_Hit_Effect JSON to set DetachedFromModel to true for improved visual consistency. Tests: All tests passing. Build: ./gradlew clean build successful.
This commit is contained in:
@@ -3,51 +3,62 @@ package com.mythlane.chainlightning.sceptre;
|
||||
import com.hypixel.hytale.component.CommandBuffer;
|
||||
import com.hypixel.hytale.component.ComponentAccessor;
|
||||
import com.hypixel.hytale.component.Ref;
|
||||
import com.hypixel.hytale.math.vector.Vector3d;
|
||||
import com.hypixel.hytale.server.core.asset.type.entityeffect.config.EntityEffect;
|
||||
import com.hypixel.hytale.server.core.entity.effect.EffectControllerComponent;
|
||||
import com.hypixel.hytale.server.core.universe.world.ParticleUtil;
|
||||
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
|
||||
import com.mythlane.chainlightning.chain.ChainHit;
|
||||
import com.mythlane.chainlightning.chain.Vec3;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/** Applies a custom EntityEffect to each chain target so the visual replicates via ECS sync. */
|
||||
/** Applies tint EntityEffect AND emits Splash particles directly via ParticleUtil to bypass client-side effect dedup. */
|
||||
public final class HytaleVfxEmitter {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(HytaleVfxEmitter.class.getName());
|
||||
|
||||
private static final String EFFECT_ID = "Chain_Hit_Effect";
|
||||
private static final String EFFECT_ID = "Chain_Hit_Effect";
|
||||
private static final String PARTICLE_ID = "Splash";
|
||||
|
||||
private HytaleVfxEmitter() {}
|
||||
|
||||
/** Resolves the EntityEffect once and adds it to every valid target via EffectControllerComponent. */
|
||||
public static void playChainEffects(@Nonnull List<ChainHit> hits,
|
||||
@Nonnull Ref<EntityStore> playerRef,
|
||||
@Nonnull CommandBuffer<EntityStore> commandBuffer) {
|
||||
if (hits.isEmpty()) return;
|
||||
|
||||
EntityEffect entityEffect = EntityEffect.getAssetMap().getAsset(EFFECT_ID);
|
||||
if (entityEffect == null) {
|
||||
LOGGER.warning(String.format(
|
||||
"[ChainLightning][Vfx] EntityEffect '%s' not registered -- VFX skipped (damage already applied)",
|
||||
EFFECT_ID));
|
||||
return;
|
||||
}
|
||||
|
||||
ComponentAccessor<EntityStore> accessor = commandBuffer;
|
||||
|
||||
int applied = 0;
|
||||
for (ChainHit hit : hits) {
|
||||
Ref<EntityStore> targetRef = HytaleEntityAdapter.from(hit).ref();
|
||||
if (!targetRef.isValid()) continue;
|
||||
EffectControllerComponent ecc = accessor.getComponent(targetRef, EffectControllerComponent.getComponentType());
|
||||
if (ecc != null && ecc.addEffect(targetRef, entityEffect, accessor)) {
|
||||
applied++;
|
||||
|
||||
// Direct particle spawn — fires on every call, no client-side dedup.
|
||||
Vec3 p = hit.target().position();
|
||||
Vector3d pos = new Vector3d(p.x(), p.y() + 1.0, p.z());
|
||||
try {
|
||||
ParticleUtil.spawnParticleEffect(PARTICLE_ID, pos, accessor);
|
||||
} catch (Throwable t) {
|
||||
LOGGER.warning("[ChainLightning][Vfx] particle spawn failed: " + t.getMessage());
|
||||
}
|
||||
|
||||
// Optional tint via EntityEffect (best-effort).
|
||||
if (entityEffect != null) {
|
||||
EffectControllerComponent ecc = accessor.getComponent(
|
||||
targetRef, EffectControllerComponent.getComponentType());
|
||||
if (ecc != null && ecc.addEffect(targetRef, entityEffect, accessor)) {
|
||||
applied++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LOGGER.info(String.format(
|
||||
"[ChainLightning][Vfx] EntityEffect '%s' applied to %d/%d targets (caster=%s)",
|
||||
EFFECT_ID, applied, hits.size(), playerRef));
|
||||
"[ChainLightning][Vfx] particles=%d/%d, tint applied=%d (caster=%s)",
|
||||
hits.size(), hits.size(), applied, playerRef));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"TargetEntityPart": "Entity",
|
||||
"Scale": 4.0,
|
||||
"Color": "#B0DCFF",
|
||||
"DetachedFromModel": false
|
||||
"DetachedFromModel": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user