dayz-particles
Overview
>
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.
.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)
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
}
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.
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).
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.
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
MyMod/
data/particles/
mymod_water_spray.ptc
mymod_overload_sparks.ptc
data/particles/materials/ ← optional custom materials
mymod_blue_water.emat
scripts/3_Game/
MyMod_ParticleList.c
Registration (3_Game layer)
modded class ParticleList
{
static const int MYMOD_WATER_SPRAY = RegisterParticle(
"MyMod/data/particles/", "mymod_water_spray");
static const int MYMOD_OVERLOAD_SPARKS = RegisterParticle(
"MyMod/data/particles/", "mymod_overload_sparks");
};
AddonBuilder filter (include .ptc .emat .edds)
*.emat;*.edds;*.meta;*.ptc;*.c;*.imageset;*.layout;*.ogg;*.json;*.xml;*.paa;*.rvmat
INTEGRATION PATTERNS — example mod (summary)
Full code: references/integration-patterns.md
Pattern A — FireplaceBase helpers: MyMod_PlayParticle(out Particle, id, pos) /
MyMod_StopParticle(out Particle) with null-safety and server guard.
Pattern B — SyncVar toggle: server sets state→SetSynchDirty, client creates/destroys in MyMod_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.
Cleanup contract: EVERY device with looping particles MUST clean up in EEDelete + MyMod_OnPowerCut + destructor.
PITFALLS AND HARD RULES
- Particles are CLIENT-ONLY. Wrap in
#ifndef SERVER. - 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 (e.g.
mymod_). - ParticleManager.GetInstance() returns null on server. Always null-check.
- 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 (277 entries).
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
REFERENCE FILES
references/vanilla-particle-catalog.md— 277 vanilla particles by categoryreferences/integration-patterns.md— 5 device-integration 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 signatures