Tribes 2 // Mod Development Handbook GitHub

Datablock classes

Every datablock type you can declare, with usage counts from the 334 files in base/scripts.vl2 [script] and the engine’s own validation ranges where they exist [binary].

Census

Type Count Purpose Recipe
AudioProfile 298 A sound Audio
EffectProfile 140 Immersion force-feedback effect Audio
ParticleData 114 One particle’s look and physics Effects
ParticleEmitterData 114 Emission pattern Effects
ExplosionData 66 Explosion assembly Effects
ItemData 58 Any pickable item Weapons, Packs
ShapeBaseImageData 35 A mountable image Weapons
StaticShapeData 35 Non-moving world object Deployables
DebrisData 18 Destruction fragments Effects
TurretImageData 17 Turret barrel Turrets
CommanderIconData 16 Command-map icon
SensorData 15 Detection behaviour Turrets
AudioDescription 13 Sound category Audio
DecalData 12 Surface marks
SimDataBlock 11 Generic script datablock — used for damage profiles Damage
RunningLightData 11 Vehicle running lights Vehicles
TurretData 10 Turret base Turrets
ShockwaveData 10 Expanding ring Effects
SplashData 9 Water entry Effects
PlayerData 9 Armor Armors
TSShapeConstructor 8 Binds .dsq sequences to a .dts Armors
TriggerData 7 Volume trigger Missions
ForceFieldBareData 6 Force field
TracerProjectileData 5 Hitscan tracer Projectiles
LinearFlareProjectileData 5 Flare-rendered linear projectile Projectiles
MissionMarkerData 4 Editor marker
JetEffectData 4 Jetpack effect Armors
GrenadeProjectileData 4 Ballistic projectile Projectiles
PrecipitationData 3 Rain and snow
ParticleEmissionDummyData 3 Standalone emitter Effects
FlyingVehicleData 3 Shrike, Havoc, Bomber Vehicles
AudioEnvironment 3 Reverb space Audio
TargetProjectileData 2 Targeting laser Projectiles
SeekerProjectileData 2 Homing missile Projectiles
HoverVehicleData 2 Wildcat, Tank Vehicles
ELFProjectileData 2 Sustained beam Projectiles
CameraData 2 Camera behaviour
WheeledVehicleData 1 MPB Vehicles
StationFXVehicleData 1 Vehicle station effect
StationFXPersonalData 1 Inventory station effect

Types used only by mission files and not declared in scripts.vl2: EnergyProjectileData (blaster), SniperProjectileData, ShockLanceProjectileData, LinearProjectileData, RepairProjectileData, and ProjectileData (abstract — “cannot be used as a concrete datablock type” [script]).

Validated field ranges

The engine validates many fields in onAdd and refuses the datablock — or clamps — if they are out of range. These messages are in the binary [binary] and are the authoritative bounds. Violating them produces a console error at load time and a datablock that does not work.

ProjectileData and descendants

Field Constraint
directDamage >= 0.0
indirectDamage >= 0.0
damageRadius >= 0.0
kickBackStrength >= 0
lightRadius [1, 20]
lifetimeMS bounded range, engine-defined
fizzleTimeMS >= 0 and <= lifetimeMS
wetVelocity >= 0.1“wetVelocity < .1, resetting”

GrenadeProjectileData

Field Constraint
grenadeElasticity [0, 0.999]“to prevent FP errors from accumulating”
grenadeFriction [0, 1]
drag [0, inf]
lifetimeMS must be non-zero

The blaster’s grenadeElasticity = 0.998 sits deliberately just under the ceiling [script].

SeekerProjectileData

Field Constraint
turningSpeed [0, 2000]
acceleration [0.0, 30000]
maxVelocity >= 0.1
muzzleVelocity >= 0.1
terrainAvoidanceSpeed [0, 2000]
terrainScanAhead [0, 200]
terrainAvoidanceRadius >= 0
terrainHeightFail >= 0
flareDistance >= 0“0 indicates missile unaffected by flares”
flareAngle >= 0 — same
flechetteDelayMs <= 30000

SniperProjectileData / TargetProjectileData

Field Constraint
maxRifleRange [10, 2000]

TracerProjectileData

Field Constraint
tracerLength [1, 50]
tracerMinPixels [1, 20]

ELFProjectileData

Field Constraint
beamRange >= 2
beamHitWidth [0, 90]

ShockLanceProjectileData

Field Constraint
zapDuration [0.05, 2.0]
boltLength [0.5, 50.0]

ParticleData

Field Constraint
lifetimeMS >= 1
lifetimeVarianceMS < lifetimeMS
spinSpeed, spinRandomMin, spinRandomMax validated
numFrames, framesPerSec validated
times[n] must be non-decreasing“times[%d] < times[%d]”

The times[] ordering rule catches people out. Keyframe times must ascend.

ParticleEmitterData

Field Constraint
ejectionPeriodMS >= 1 ms
periodVarianceMS < ejectionPeriodMS
ejectionVelocity >= 0.0
ejectionOffset >= 0
thetaMin >= 0.0 and <= thetaMax
thetaMax <= 180.0
phiVariance validated
lifetimeVarianceMS < lifetimeMS
particles must name at least one existing ParticleData; the string is capped at 255 characters

“invalid particles string. No datablocks found” and “particle string too long [> 255 chars]” are the two failure messages. The second bites when you list many particle types in one emitter.

ExplosionData

Field Constraint
lifetimeMS >= 1
lifetimeVariance <= lifetimeMS
delayMS >= 0
delayVariance <= delayMS
offset >= 0.0
debrisNum, debrisNumVariance <= 1000
debrisThetaMin >= 0.0 and <= debrisThetaMax
debrisPhiMin >= 0.0 and <= debrisPhiMax
debrisPhiMax <= 360.0

DebrisData

Field Constraint
lifetime, lifetimeVariance validated
elasticity, friction validated
numBounces, bounceVariance validated
velocity, velocityVariance validated
minSpinSpeed, maxSpinSpeed validated

TurretData / TurretImageData

Field Constraint
thetaMin [0, 90]
degPerSecTheta [1, 1080]
activationMS [engine min, 5000]
deactivateDelayMS [engine min, 5000]
thinkTimeMS [engine min, 5000]

ForceFieldBareData

Field Constraint
fadeMS [0, 10000]

PrecipitationData

Field Constraint
sizeX (0, 20]

Declaring a datablock

datablock <Type>(<Name>)
{
   field = value;
};

datablock <Type>(<Name>) : <ParentName>
{
   field = value;      // everything else inherited
};

Rules:

  • The parent must exist at declaration time.
  • Referenced datablocks must exist at declaration time — see Datablocks.
  • Unknown fields become dynamic fields — no error, no effect on the engine, readable from script.
  • className selects the script dispatch namespace, and is how ItemData becomes a weapon, a pack, or hand inventory.

The className values

className Handlers in Behaviour you inherit
Weapon scripts/weapons.cs onUse (mount to $WeaponSlot), onInventory, onPickup, incCatagory
Ammo scripts/weapons.cs onInventory — drives image ammo state and HUD
WeaponImage scripts/weapons.cs onMount / onUnmount — arm thread, HUD, reticle
Pack scripts/pack.cs onCollision, onUse (toggle trigger), onInventory (auto-mount)
HandInventory scripts/weapons.cs onUse (the throw code), onInventory
HandInventoryImage scripts/weapons.cs onMount
Armor scripts/player.cs Player behaviour; required for weapons to mount
TurretBase scripts/turret.cs Turret base behaviour

Setting className to an existing value is the cheapest way to get a complete behaviour set. See SimObjects and namespaces.

Under the community patches

No datablock types are added, removed, or changed, and every validated range above still applies — the validation lives in Tribes2.exe, which neither patch modifies.

One type is functionally inert on the QoL patch: EffectProfile (140 declared in the shipped scripts). The blocks still parse and AudioProfile.effect still accepts them, but TribesNEXT’s IFC22.dll stubs the Immersion force-feedback exports [binary], so nothing plays. Declaring them remains harmless; omitting them was always fine. RC2a keeps the vendor DLL and force feedback works.

Everything else — every field, every range, every className dispatch value — is identical.