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.
In this repository47 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- .github/copilot-instructions.mdCopilot instructions
- 3d-generation-harnessSkill
- ai-3d-to-dayzSkill
- ardy-motion-generationSkill
- blender-animationSkill
- blender-assemblySkill
- blender-visual-reviewSkill
- dayz-3d-viewerSkill
- dayz-ai-patternsSkill
- dayz-animation-pipelineSkill
- dayz-aviationSkill
- dayz-basebuildingSkill
- dayz-charactersSkill
- dayz-clothingSkill
- dayz-doorsSkill
- dayz-environment-hazardsSkill
- dayz-feature-specSkill
- dayz-mcp-verifySkill
- dayz-model-pipelineSkill
- dayz-mod-workflowSkill
- dayz-motorbikesSkill
- dayz-p3d-auditSkill
- dayz-p3d-inspectorSkill
- dayz-pbo-buildSkill
- dayz-pbo-reverse-engineeringSkill
- dayz-persistenceSkill
- dayz-physics-engineSkill
- dayz-preflightSkill
- dayz-proxy-alignSkill
- dayz-realistic-animation-directorSkill
- dayz-sound-systemSkill
- dayz-test-ingameSkill
- dayz-texture-pipelineSkill
- dayz-ui-developmentSkill
- dayz-undergroundSkill
- dayz-vehiclesSkill
- dayz-weaponsSkill
- enforce-script-referenceSkill
- mixamo-retargetSkill
- ovh-cloudSkill
- rigorous-data-auditSkill
- rip-vehicle-importSkill
- systematic-debuggingSkill
- task-observerSkill
- uv-clean-atlasSkill
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
- Very specific: line 20
All particles are CLIENT-ONLY.
- Distinctive: line 136
Mod .ptc→vanilla .emat: USE vanilla GUID+path (mandatory, verified)
- Distinctive: line 137
Mod .emat→vanilla .edds: USE vanilla GUID+path (safe)
- Very specific: line 161
All paths prefixed with Graphics/Particles/materials/.
- Distinctive: line 275
Cleanup contract: EVERY device with looping particles MUST clean up in EEDelete + LFPG_OnWiresCut + destructor.
- Distinctive: line 284
Looping particles (Repeat 1) NEVER end: MUST Stop() + null ref.
- Distinctive: line 285
Stop() is gradual: Use StopParticleFlags.IMMEDIATE for instant removal.
- Very specific: line 300
GUIDs mandatory: when referencing vanilla .emat/.edds from mod .ptc.
- Distinctive: line 346
Run these gates before choosing a large contaminated-area radius.
- Very specific: line 393
Treat JsonDataContaminatedArea as the schema authority (VANILLA/scripts/4_world/classes/contaminatedarea/jsondatacontaminatedarea.c:17-34).
≈ “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.
Files
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.
| Layer | Format | Creatable? | Purpose |
.ptc | Plain text config | YES | Particle effect (emitters, physics, curves) |
.emat | Plain text config | YES | Material (texture ref, blend mode, color) |
.edds | Standard DDS renamed | YES | Billboard sprite texture |
.meta | Plain text (GUIDs) | Workbench only | NOT 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:
| GUID | Short name | Visual type |
{CB7AF4FD8ACBFDFC} | glow/glow1.emat | Soft glow dot |
{009C2EBAACD2D72A} | fire/sparks1.emat | Bright spark point |
{0B829A150C6A13E5} | fire/sparks_06.emat | Spark strip (8-tile) |
{853257EDA4B1E35D} | fire/fire_flame_01.emat | Fire flame billboard |
{3E6CE4D61F8AC71F} | fire/fire_medium_camp_02.emat | Medium fire anim |
{83BCB6516091DB01} | fire/fire_medium_camp_04.emat | Fire burst anim |
{62F13B8B540EBC80} | fire/fireball_1.emat | Fireball |
{00BEA27443975BEB} | smoke/smoke_anim_02.emat | Animated smoke puff |
{008E25684854DAB8} | smoke/steam_small_cook_01.emat | Steam/vapor cloud |
{8FE2383D6913E098} | enviroment/water_splash_01_NoEm.emat | Water splash |
{D29B53088A5A3911} | smoke/smoke_dust_01_W.emat | White 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.cRegistration (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;*.rvmatLFPG 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
- 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 useCreateParticleServer, not PlayOnObject.) - Looping particles (Repeat 1) NEVER end. MUST Stop() + null ref.
- Stop() is gradual. Use StopParticleFlags.IMMEDIATE for instant removal.
- ObjectDelete(particle) valid for ParticleSource with DisableAutoDestroy().
- Render distance ~200m. Engine limit, no workaround.
- Duplicate filenames across mods: use unique prefixes (
lfpg_). - 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-referencehard rules 19-20. - SEffectManager.DestroyEffect() is the ONLY safe Effect cleanup.
- AIR_RESISTANCE controls smoke rise. FireplaceBase adjusts for ceilings.
- force_world_rotation=true for smoke/steam that should always rise up.
- .meta files NOT needed for mod runtime.
- GUIDs mandatory when referencing vanilla .emat/.edds from mod .ptc.
- .ptc is PLAIN TEXT. Can be generated by Python scripts, no Workbench needed.
- 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 patternsreferences/ptc-format-reference.md— 56-property .ptc reference with vanilla examplesreferences/emat-format-reference.md— .emat format, both shader types, all 12 propertiesreferences/script-api-reference.md— Particle/ParticleSource/ParticleManager signaturesreferences/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_FloatModifiersviaVehicleVFXComponent. - Surface particle IDs move to
SurfaceInfo.GetStepParticleId/GetWheelParticleId/GetVehicleDustParticleId/GetCeilingDustParticleId(theSurface.GetStepsParticleID/GetWheelParticleIDwrappers are[Obsolete]). - Effect areas:
OnCEIteratereplacesOnCEUpdate;SpawnParticlesprefersSurfaceRoadY. - New ParticleList constants: tandoor, desert/mud-brick impacts,
CEILING_WOOD, dust,OIL_FIRE1/OIL_FIRE2. Weather sandstorm is aSnowEffectpostprocess.ematplusparticlePath = "Graphics/Particles/sandstorm/sandstorm".
What breaks (1.29 mods)
| Symptom | Severity | Change |
| Particles play on headless client | MEDIUM | Replace !IsDedicatedServer() with !IsHeadlessOrDedicatedServer(). |
| Wheel/step particles ignore custom surfaces | MEDIUM | Stop calling Surface.GetStepsParticleID / GetWheelParticleID; use SurfaceInfo. |
EffWheelSmoke.SetSurface(string) | LOW | Use SelectFromSurface(SurfaceInfo). |
Custom EffectArea never ticks / particles float above bridges | MEDIUM | Override OnCEIterate; snap with SurfaceRoadY. |
1.30 migration checklist
- Search the mod for
IsDedicatedServer()on particle spawn; switch VFX toIsHeadlessOrDedicatedServer(). - Replace
Surface.GetStepsParticleID/GetWheelParticleIDwithSurfaceInfo.GetByName(...).GetStepParticleId()/GetWheelParticleId(). - Replace
EffWheelSmoke.SetSurfacewithSelectFromSurface. - Custom EffectArea:
OnCEIterate(float currentTime, float elapsedTime)andSurfaceRoadY. - Vehicle dust/exhaust: register through
VehicleVFXComponentand overrideParticleParamsOverride. - Do not copy
sandstorm.ematas a particle material — shader isSnowEffect.
1.30 references in this skill
- DayZ 1.30 particles
- Script API 1.30
- Vanilla catalog 1.30 constants
- PlayOnObject client gate
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
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.

