agentleFS
willy92winswilly92wins/DayZ-Modding-Knowledge-Pack/skills/dayz-particles/SKILL.md

dayz-particles

Skill20 starsChanged 42 days agoMITView on GitHub

Use when: particles, .ptc, .emat, ParticleSource, SEffectManager, PlayOnObject, cfgeffectarea, smoke/sparks without Workbench, sandstorm, ceiling dust, ParticleParamsOverrideData, VehicleVFX, IsHeadlessOrDedicatedServer. Client-only .ptc/.emat. Not sound: dayz-sound-system.

The file

We split this skill into the rules it gives an agent

10 rules. About 0 are common, 6 are distinctive, and 4 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈6

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 4

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    All particles are CLIENT-ONLY.

    line 20
  2. Distinctive:

    Mod .ptc→vanilla .emat: USE vanilla GUID+path (mandatory, verified)

    line 136
  3. Distinctive:

    Mod .emat→vanilla .edds: USE vanilla GUID+path (safe)

    line 137
  4. Very specific:

    All paths prefixed with Graphics/Particles/materials/.

    line 161
  5. Distinctive:

    Cleanup contract: EVERY device with looping particles MUST clean up in EEDelete + LFPG_OnWiresCut + destructor.

    line 275
  6. Distinctive:

    Looping particles (Repeat 1) NEVER end: MUST Stop() + null ref.

    line 284
  7. Distinctive:

    Stop() is gradual: Use StopParticleFlags.IMMEDIATE for instant removal.

    line 285
  8. Very specific:

    GUIDs mandatory: when referencing vanilla .emat/.edds from mod .ptc.

    line 300
  9. Distinctive:

    Run these gates before choosing a large contaminated-area radius.

    line 346
  10. Very specific:

    Treat JsonDataContaminatedArea as the schema authority (VANILLA/scripts/4_world/classes/contaminatedarea/jsondatacontaminatedarea.c:17-34).

    line 393

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

DayZ Particle Effects — Complete Modding Reference

CRITICAL: .ptc AND .emat ARE PLAIN TEXT

DayZ particle files (.ptc) and material files (.emat) are plain text configs, not binary. Custom particles can be created programmatically without Workbench.

LayerFormatCreatable?Purpose
.ptcPlain text configYESParticle effect (emitters, physics, curves)
.ematPlain text configYESMaterial (texture ref, blend mode, color)
.eddsStandard DDS renamedYESBillboard sprite texture
.metaPlain text (GUIDs)Workbench onlyNOT needed for mod runtime

All particles are CLIENT-ONLY. Server controls state via SyncVars; client creates/destroys particles in response. (until 1.29: this was the documented PlayOnObject contract; wrecks gated with !g_Game.IsDedicatedServer(). SEffectManager.CreateParticleServer already existed for trees/fishing/traps.) (since 1.30 Exp: local PlayOnObject is still client-only, but ceiling dust and other synced effecters spawn on the server via CreateParticleServer; vanilla wrecks, FireplaceBase, and ParticleManager.GetInstance() now gate with !g_Game.IsHeadlessOrDedicatedServer(). Details: references/dayz-1-30-particles.md.)

EFFECT-AREA PREFLIGHT (added 2026-08-31)

For cfgeffectarea.json, run Effect areas: emitter budget and vertical band plus its correction below before choosing a radius. Compute the exact per-ring upper budget, keep it below 1,000 with margin, measure the full elevation/underground band, and compare every global SafePositions entry against every area.


.ptc FILE FORMAT (verified from 9 vanilla files)

One EffectDef with one or more EmitorDef blocks. Each emitter is an independent particle stream. Simplest particle (debug_dot): 1 emitter, 478 bytes. Complex fire (fire_small_camp_01): 6 emitters (glow + flames + burst + short + sparks + smoke).

EffectDef {
 Emitors {
  EmitorDef <name> {
   ShapeType Point
   MaxNum 10
   BirthRate 5
   Material "{GUID}path/to/material.emat"
   SizeMultiplier 0.5
   Velocity 2
   LifeTime 1.5
   Color {
    0 1 0.8 0.3 1 0.7 0.5 0.25
   }
   Alpha {
    0 0 0.2 1 1 0
   }
   Repeat 1
  }
 }
}

Property categories (56 total — full list in references/ptc-format-reference.md)

Shape & emission: ShapeType (Point/Box/Ellipse), ShapeSize (x y z), ConeAngle (yaw pitch roll deg), MaxNum, BirthRate, BirthRateRND, Offset (x y z)

Visual: Material ("{GUID}path.emat"), SizeMultiplier, SizeRND, BillboardingType (Full), CenterY (-1=bottom, 0=center), StretchMultiplier

Motion: Velocity, VelocityRND, AirResistance, AirResistanceRND, GravityMultiply, GravityMultiplyRND, Wind (0-1), Spring, Restitution, VelAngle (0/1), VelAffect (0-1) (since 1.30 Exp: after play, EffectParticle.ParticleParamsOverride(ParticleParamsOverrideData) can retune EmitorParam.LIFETIME / VELOCITY / SIZE / AIR_RESISTANCE from script — used by vehicle dust and wheel contact. See references/dayz-1-30-particles.md.)

Lifetime: LifeTime (seconds), LifeTimeRND, EffectTime (cycle duration), Repeat (0=one-shot auto-deletes, 1=loop MUST stop manually)

Animation: AnimOnce, AnimFPS, LifetimeByAnim, RandomFrame

Rotation: RandomRotDir, RotMultiplier, RandomAngle

Curves (keyframe pairs: time value time value ...): Color { t r g b t r g b }, Alpha { t a t a }, Size { t s t s }, RotationSpeed { t s t s }

Master curves (modulate over EffectTime): ColorMast, AlphaMast, SizeMast, BRateMast, VelocityMast, AirResistanceMast


.emat MATERIAL FORMAT (verified from 8 vanilla materials)

Shader: Particle (fire, sparks, water, most particles)

Particle {
 AlbedoMap "{GUID}Graphics/Particles/sprites/texture.edds"
 Color 0 0 0 1
 Emissive 1 1 1 0
 BlendMode Additive_AlphaModulate
 Sort translucent
 Softness 2
 TileU 4
 TileV 2
}

(until 1.29: particle .emat shaders documented here are Particle and ParticleSprite.) (since 1.30 Exp: weather VFX also ship postprocess .emat that are not particle materials — sandstorm uses shader SnowEffect in exp\graphics\graphics\Materials\postprocess\sandstorm.emat:1. Do not treat that file as a .ptc material.)

Shader: ParticleSprite (steam, flares, glow billboards)

ParticleSprite {
 AlbedoMap "{GUID}Graphics/Particles/sprites/texture.edds"
 Color 0.95 0.95 0.95 1
 Diffuse 0.95 0.95 0.95 1
 Ambient 0.59 0.59 0.59 1
 Softness 2
}

All .emat properties (12):

AlbedoMap (texture GUID+path), Color (RGBA 0-1), Diffuse (RGBA), Ambient (RGBA), Emissive (RGBA, self-glow), BlendMode (Additive_AlphaModulate or numeric), Sort (translucent/overlay/0), Softness (0-2, edge blending), TileU/TileV (sprite sheet cols/rows), CameraBlendFar (distance fade), BidirLightScale (bidirectional lighting)

Full reference with examples: references/emat-format-reference.md


GUID REFERENCE SYSTEM

Resources reference each other via {HEXGUID}relative/path.ext.

  • Vanilla→vanilla: GUIDs embedded, engine resolves by GUID first
  • Mod .ptc→vanilla .emat: USE vanilla GUID+path (mandatory, verified)
  • Mod .emat→vanilla .edds: USE vanilla GUID+path (safe)
  • Mod .ptc→mod .emat: path-only may work (needs in-game testing)
  • .meta files NOT needed for mod runtime loading

VANILLA MATERIAL LIBRARY (11 GUIDs mapped)

Reference these in custom .ptc to reuse vanilla visuals:

GUIDShort nameVisual type
{CB7AF4FD8ACBFDFC}glow/glow1.ematSoft glow dot
{009C2EBAACD2D72A}fire/sparks1.ematBright spark point
{0B829A150C6A13E5}fire/sparks_06.ematSpark strip (8-tile)
{853257EDA4B1E35D}fire/fire_flame_01.ematFire flame billboard
{3E6CE4D61F8AC71F}fire/fire_medium_camp_02.ematMedium fire anim
{83BCB6516091DB01}fire/fire_medium_camp_04.ematFire burst anim
{62F13B8B540EBC80}fire/fireball_1.ematFireball
{00BEA27443975BEB}smoke/smoke_anim_02.ematAnimated smoke puff
{008E25684854DAB8}smoke/steam_small_cook_01.ematSteam/vapor cloud
{8FE2383D6913E098}enviroment/water_splash_01_NoEm.ematWater splash
{D29B53088A5A3911}smoke/smoke_dust_01_W.ematWhite dust/mist

All paths prefixed with Graphics/Particles/materials/.


THREE SCRIPT API LAYERS

1. Legacy Particle (scripts/3_Game/Particles/Particle.c)

Creates #particlesourceenf child entity. EOnFrame lifetime tracking. Auto-deletes non-looping particles. Used by FireplaceBase, torches, cooking.

2. ParticleSource extends Particle (ParticleSource.c)

Native C++ backed. No EOnFrame. Auto-destroy flags: ON_END, ON_STOP, ALL, NONE. StopParticleFlags: NONE = 0 (no-op; default StopParticle() already does gradual fade), IMMEDIATE, PAUSE (freeze visible).

3. ParticleManager pool (ParticleManager.c)

Global instance via ParticleManager.GetInstance() — 10000 pool, client only, returns null on dedicated server. Pre-allocates+reuses ParticleSource objects. (until 1.29: GetInstance skipped create when IsDedicatedServer().) (since 1.30 Exp: skipped when IsHeadlessOrDedicatedServer() — headless clients also get null. exp\scripts\scripts\3_Game\Particles\ParticleManager\ParticleManager.c:65.) Mods can also new ParticleManager(settings) to instantiate their own pools (the test framework does this); GetInstance() is the global, not a hard singleton.

Wrapper: SEffectManager

PowerGenerator pattern: SEffectManager.PlayOnObject(effect, parent, pos, ori). Cleanup: SEffectManager.DestroyEffect(m_Smoke). (since 1.30 Exp: synced spawn uses SEffectManager.CreateParticleServer(pos, EffecterParameters) — ceiling dust: DustEffectCeilingHandlerSynced. exp\scripts\scripts\3_Game\EffectManager.c:586.)

Full API signatures: references/script-api-reference.md


API QUICK REFERENCE

// Static create+play
Particle p = Particle.PlayOnObject(ID, parent, localPos, localOri, forceWorldRot);
Particle p = Particle.PlayInWorld(ID, worldPos);
// ParticleManager.GetInstance() returns null on dedicated server — always guard.
// (since 1.30 Exp: also null on headless — use !g_Game.IsHeadlessOrDedicatedServer().)
ParticleManager pm = ParticleManager.GetInstance();
ParticleSource ps;
if (pm) ps = pm.PlayOnObject(ID, parent, localPos);

// Instance control
p.PlayParticle(optionalNewId);
p.StopParticle(flags);  // StopParticleFlags: NONE, IMMEDIATE, PAUSE
p.Stop();               // legacy alias
p.IsParticlePlaying();
p.ResetParticle();      // ParticleSource only
p.RestartParticle();    // reset+play
p.DisableAutoDestroy(); // ParticleSource only

// Parameter tuning (-1 = all emitters)
p.SetParameter(emitter, EmitorParam.AIR_RESISTANCE, 3.0);
p.ScaleParticleParamFromOriginal(EmitorParam.SIZE, 0.5);

// Wiggle
p.SetWiggle(randomAngle, randomInterval);
p.StopWiggle();

REGISTERING CUSTOM PARTICLES

Mod file structure

LFPowerGrid/
  data/particles/
    lfpg_sprinkler_spray.ptc
    lfpg_overload_sparks.ptc
  data/particles/materials/         ← optional custom materials
    lfpg_blue_water.emat
  scripts/3_Game/
    LFPG_ParticleList.c

Registration (3_Game layer)

modded class ParticleList
{
    static const int LFPG_SPRINKLER_SPRAY = RegisterParticle(
        "LFPowerGrid/data/particles/", "lfpg_sprinkler_spray");
    static const int LFPG_OVERLOAD_SPARKS = RegisterParticle(
        "LFPowerGrid/data/particles/", "lfpg_overload_sparks");
};

AddonBuilder filter (include .ptc .emat .edds)

*.emat;*.edds;*.meta;*.ptc;*.c;*.imageset;*.layout;*.ogg;*.json;*.xml;*.paa;*.rvmat

LFPG INTEGRATION PATTERNS (summary)

Full code: references/lfpg-integration-patterns.md

Pattern A — FireplaceBase helpers: LFPG_PlayParticle(out Particle, id, pos) / LFPG_StopParticle(out Particle) with null-safety and server guard.

Pattern B — SyncVar toggle: server sets state→SetSynchDirty, client creates/destroys in LFPG_OnVarSync.

Pattern C — One-shot sparks: non-looping (Repeat 0) particles auto-delete, no cleanup needed. Use for overload events.

Pattern D — SEffectManager wrapper: for combining particle+sound. Cleanup ONLY via SEffectManager.DestroyEffect().

Pattern E — Runtime parameter tuning: SetParameter for AIR_RESISTANCE, ScaleParticleParamFromOriginal for SIZE. (since 1.30 Exp: vehicle VFX use ParticleParamsOverride(ParticleParamsOverrideData) instead of ad-hoc SetParameter after Play.)

Cleanup contract: EVERY device with looping particles MUST clean up in EEDelete + LFPG_OnWiresCut + destructor.


PITFALLS AND HARD RULES

  1. Particles are CLIENT-ONLY. Wrap in #ifndef SERVER. (until 1.29: PlayOnObject gated with !IsDedicatedServer().) (since 1.30 Exp: vanilla uses !g_Game.IsHeadlessOrDedicatedServer() so headless clients also skip VFX. Server-spawned effecters use CreateParticleServer, not PlayOnObject.)
  2. Looping particles (Repeat 1) NEVER end. MUST Stop() + null ref.
  3. Stop() is gradual. Use StopParticleFlags.IMMEDIATE for instant removal.
  4. ObjectDelete(particle) valid for ParticleSource with DisableAutoDestroy().
  5. Render distance ~200m. Engine limit, no workaround.
  6. Duplicate filenames across mods: use unique prefixes (lfpg_).
  7. ParticleManager.GetInstance() returns null on server. Always null-check. (since 1.30 Exp: also null on headless clients — IsHeadlessOrDedicatedServer().) Guards 1 and 7 are complementary, not redundant: #ifndef SERVER (pitfall 1) is compile-time exclusion for whole client-only blocks; the null-check (this pitfall) is runtime safety for code compiled on both sides (a diag/SP client-server build has no SERVER define but still runs server-side). Side checks: enforce-script-reference hard rules 19-20.
  8. SEffectManager.DestroyEffect() is the ONLY safe Effect cleanup.
  9. AIR_RESISTANCE controls smoke rise. FireplaceBase adjusts for ceilings.
  10. force_world_rotation=true for smoke/steam that should always rise up.
  11. .meta files NOT needed for mod runtime.
  12. GUIDs mandatory when referencing vanilla .emat/.edds from mod .ptc.
  13. .ptc is PLAIN TEXT. Can be generated by Python scripts, no Workbench needed.
  14. EffectTime + Repeat interact: EffectTime is the master curve cycle, Repeat loops the entire effect. One-shot (Repeat 0) plays once for EffectTime duration.

VANILLA PARTICLE CATALOG — KEY CATEGORIES

Full catalog: references/vanilla-particle-catalog.md (276 entries; version-dependent). (since 1.30 Exp: new constants include tandoor fireplace, desert/mud-brick impacts, ceiling dust, vehicle dust, oil-pit fire, sand grenade explosions — listed in that catalog's 1.30 section.)

Electricity

POWER_GENERATOR_SMOKE (1 emitter, loop), BARBED_WIRE_SPARKS (1 emitter, one-shot)

Water

WATER_JET (2 emitters, loop), WATER_JET_WEAK (2 emitters, loop), WATER_SPILLING, DROWNING_BUBBLES

Fire

CAMP_SMALL_FIRE (6 emitters), CAMP_STOVE_FIRE, BONFIRE_FIRE

Smoke/Steam

CAMP_SMALL_SMOKE (1 emitter), CAMP_STEAM_2END, EVAPORATION, SPOOKY_MIST

Environment

ENV_SWARMING_FLIES, SMOKING_HELI_WRECK, HOTPSRING_WATERVAPOR, GEYSER_NORMAL, GEYSER_STRONG, VOLCANO (since 1.30 Exp: OIL_FIRE1/OIL_FIRE2, DUST_GROUND/DUST_CLOUD/DUST_VEHICLE, CEILING_WOOD. Weather sandstorm also references Graphics/Particles/sandstorm/sandstorm.)


REFERENCE FILES

  • references/standalone-particle-reference.md — standalone predecessor reference: multi-emitter composition (PLANES_EX/IMPACT/BOOM), animated + Mast curves, CfgCloudlets conversion. [merged 2026-06-05]
  • references/vanilla-particle-catalog.md — 276 vanilla particles by category (version-dependent)
  • references/lfpg-integration-patterns.md — 5 LFPG code patterns
  • references/ptc-format-reference.md — 56-property .ptc reference with vanilla examples
  • references/emat-format-reference.md — .emat format, both shader types, all 12 properties
  • references/script-api-reference.md — Particle/ParticleSource/ParticleManager signatures
  • references/answeroverflow-2026-05-17.md — community snippets verified vs vanilla (PlayOnObject pattern with client guard)
  • references/dayz-1-30-particles.md — DayZ 1.30 Exp: dust, VehicleVFX, ParticleParamsOverrideData, sandstorm, oil pits, SurfaceInfo IDs, migration

Effect areas (cfgeffectarea.json): emitter budget and vertical band (added 2026-08-31)

Run these gates before choosing a large contaminated-area radius.

Hard particle budget

Each effect area has a hard cap of 1,000 emitters: const int PARTICLES_MAX = 1000 (VANILLA/scripts/4_world/classes/contaminatedarea/effectarea.c:84), enforced while SpawnParticles fills the area (:421). Exceeding it does not shrink the damage radius. The area can remain lethal beyond the visible particle core and logs Not enough particles in pool for EffectArea (:440). A valid JSON and a booting server do not prove that the perimeter is visible.

For the static FillWithParticles route, budget first with:

N = ceil((Radius + OuterOffset - InnerPartDist/2) / InnerPartDist)
emitters ~= 6.283 * N^2 * (VerticalLayers + 1)

Vanilla computes circumference = 2 * Math.PI2 * ringRadius (effectarea.c:389) while Math.PI2 is already 6.28318530717958 (VANILLA/scripts/1_core/proto/enmath.c:13). That quirk uses approximately 4*pi*r, twice the ordinary circumference. Budgeting with 2*pi*r therefore under-counts. Increasing InnerPartDist lowers the ring count N; it does not reduce the emitter count within an existing ring.

For static areas, only InnerPartDist and OuterOffset feed this route (contaminatedarea.c:70). InnerRingCount, OuterPartDist, and OuterRingToggle belong to PlaceParticles and are inert here. Do not tune them to solve a static-area density problem.

Damage and visibility are vertically bounded

The trigger is a finite cylinder, built by SetCollisionCylinderTwoWay(radius, -(NegHeight + c), PosHeight - c) with c = (PosHeight - NegHeight) * 0.5 (effectarea.c:495-497). Particle placement is culled against the same band after snapping to terrain (:413,421). Choose PosHeight and NegHeight from the actual elevation range inside the radius, not from a small vanilla zone. Underground spaces also count: particles snap to SurfaceY and are never spawned below terrain, so a bunker can be lethal inside the cylinder while showing no gas. That can be deliberate, but it must not be accidental. (until 1.29: SpawnParticles wrote partPos[1] = g_Game.SurfaceY(...).) (since 1.30 Exp: it prefers g_Game.SurfaceRoadY when the particle is above the road surface — bridges/roads. exp\scripts\scripts\4_World\Classes\ContaminatedArea\EffectArea.c:414-417. Tick hook is OnCEIterate, not OnCEUpdate.)

Safe positions and schema

SafePositions is global, not attached to one area. GetClosestSafePos searches the whole array in 2D (VANILLA/scripts/4_world/static/miscgameplayfunctions.c:1698,1717) during the early-presence rescue path (:1692; caller areaexposure.c:44). After any radius change, measure every safe position against every area; a rescue point inside another cylinder can teleport a reconnecting player from gas to gas.

Treat JsonDataContaminatedArea as the schema authority (VANILLA/scripts/4_world/classes/contaminatedarea/jsondatacontaminatedarea.c:17-34). Community fields named InnerRingRatio and OuterRingRatio are not in that schema. Large-radius height values remain [VERIFY IN GAME] until the real terrain and underground depth are measured.

Correction: effect-area budget and pool diagnostics (added 2026-08-31)

This section supersedes the approximate 6.283 * N^2 budget and the RPT claim above. For the normal large-area branch (R >= 1.25 * s), use the same rounded ring spacing and per-ring floors as FillWithParticles:

R = Radius + OuterOffset
s = max(InnerPartDist, 1)
N = ceil((R - s/2) / s)
d = (R - s/2) / N
XZ = 1 + sum(floor(2 * PI2 * d * k / s), k = 1..N)
budget_max = XZ * (VerticalLayers + 1)

PI2 is 2*pi, so the source's 2 * PI2 * ringRadius remains the intentional doubled circumference. The center emitter is the leading 1. Small areas take separate one-ring/center branches in effectarea.c:360-373; use those branches directly rather than this large-area formula. As a check, Radius=500, OuterOffset=20, InnerPartDist=70, and VerticalLayers=1 give N=7, d=69.286, XZ=346, and budget_max=692.

Reaching PARTICLES_MAX truncates additional visual emitters in SpawnParticles (effectarea.c:411-426) but does not itself log Not enough particles in pool. That error is in InsertParticles and means ParticleManager returned fewer objects than the count requested (:429-447). Do not use the RPT message as the cap gate. Vertical culling can reduce the actual count, but an approximation that under-counts cannot authorize a radius; calculate the upper budget and confirm the visible perimeter in game.

DayZ 1.30 Exp (build 1.30.164014)

Full detail: references/dayz-1-30-particles.md. Surface-dust / ceiling-dust / VehicleVFX / sandstorm .ptc path live there.

What changes

  • Client VFX gate is !g_Game.IsHeadlessOrDedicatedServer() (wrecks, FireplaceBase, ParticleManager).
  • Synced ceiling dust: SEffectManager.CreateParticleServer + ParticleEffecterParameters("CeilingDustEffecter", ...).
  • Runtime retune: ParticleParamsOverrideData.m_FloatModifiers via VehicleVFXComponent.
  • Surface particle IDs move to SurfaceInfo.GetStepParticleId / GetWheelParticleId / GetVehicleDustParticleId / GetCeilingDustParticleId (the Surface.GetStepsParticleID / GetWheelParticleID wrappers are [Obsolete]).
  • Effect areas: OnCEIterate replaces OnCEUpdate; SpawnParticles prefers SurfaceRoadY.
  • New ParticleList constants: tandoor, desert/mud-brick impacts, CEILING_WOOD, dust, OIL_FIRE1/OIL_FIRE2. Weather sandstorm is a SnowEffect postprocess .emat plus particlePath = "Graphics/Particles/sandstorm/sandstorm".

What breaks (1.29 mods)

SymptomSeverityChange
Particles play on headless clientMEDIUMReplace !IsDedicatedServer() with !IsHeadlessOrDedicatedServer().
Wheel/step particles ignore custom surfacesMEDIUMStop calling Surface.GetStepsParticleID / GetWheelParticleID; use SurfaceInfo.
EffWheelSmoke.SetSurface(string)LOWUse SelectFromSurface(SurfaceInfo).
Custom EffectArea never ticks / particles float above bridgesMEDIUMOverride OnCEIterate; snap with SurfaceRoadY.

1.30 migration checklist

  • Search the mod for IsDedicatedServer() on particle spawn; switch VFX to IsHeadlessOrDedicatedServer().
  • Replace Surface.GetStepsParticleID / GetWheelParticleID with SurfaceInfo.GetByName(...).GetStepParticleId() / GetWheelParticleId().
  • Replace EffWheelSmoke.SetSurface with SelectFromSurface.
  • Custom EffectArea: OnCEIterate(float currentTime, float elapsedTime) and SurfaceRoadY.
  • Vehicle dust/exhaust: register through VehicleVFXComponent and override ParticleParamsOverride.
  • Do not copy sandstorm.emat as a particle material — shader is SnowEffect.

1.30 references in this skill

  • DayZ 1.30 particles
  • Script API 1.30
  • Vanilla catalog 1.30 constants
  • PlayOnObject client gate

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.