Skip to main content

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.

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.


.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 &#123; t r g b t r g b &#125;, Alpha &#123; t a t a &#125;, Size &#123; t s t s &#125;, RotationSpeed &#123; t s t s &#125;

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 &#123;HEXGUID&#125;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
&#123;CB7AF4FD8ACBFDFC&#125;glow/glow1.ematSoft glow dot
&#123;009C2EBAACD2D72A&#125;fire/sparks1.ematBright spark point
&#123;0B829A150C6A13E5&#125;fire/sparks_06.ematSpark strip (8-tile)
&#123;853257EDA4B1E35D&#125;fire/fire_flame_01.ematFire flame billboard
&#123;3E6CE4D61F8AC71F&#125;fire/fire_medium_camp_02.ematMedium fire anim
&#123;83BCB6516091DB01&#125;fire/fire_medium_camp_04.ematFire burst anim
&#123;62F13B8B540EBC80&#125;fire/fireball_1.ematFireball
&#123;00BEA27443975BEB&#125;smoke/smoke_anim_02.ematAnimated smoke puff
&#123;008E25684854DAB8&#125;smoke/steam_small_cook_01.ematSteam/vapor cloud
&#123;8FE2383D6913E098&#125;enviroment/water_splash_01_NoEm.ematWater splash
&#123;D29B53088A5A3911&#125;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. 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

  1. Particles are CLIENT-ONLY. Wrap in #ifndef SERVER.
  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 (e.g. mymod_).
  7. ParticleManager.GetInstance() returns null on server. Always null-check.
  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 (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 category
  • references/integration-patterns.md — 5 device-integration 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