Skip to main content

Alchemy

Overview

Alchemy is a particle effects system in Freelancer rendering. Almost all visual effects are made in this system, like weapon projectiles, explosions, engine exhausts and many more.

Alchemy data is presented by two entries in UTF:

  • ALEffectLib for effect library.
  • AlchemyNodeLibrary for node library.

Both entries appear in .ale files inside folder entries of same names.

Strings in ALE structures (astring) are NUL-terminated and prefixed by character count as uint16. Number of characters is always even regardless of actual string length: there will always be one or two NUL bytes at the end of string.

Alchemy Effect Library

Effect library contains effect entries which are referenced in effect .ini files via effect_crc property of [VisEffect] section.

NameTypeDescription
versionfloatVersion (1.0 or 1.1).
effectCountuint32Effects count.
effectsvarying

Effect

A single effect is comprised of hierarchy of node instances which reference node archetypes in Alchemy node library. These nodes typically fall into three categories: emitters, appearances and fields.

Emitters generate particles (points in space with direction and velocity), appearances visualize particles to be rendered with certain shapes, colors and textures, and fields can affect particles physically like applying gravity force to accelerate particles.

NameTypeDescription
nameastringEffect name (ex.: "gf_jumpgate_rings").
unusedfloat[4]Unused floats.
instanceCountuint32Node instances count.
nodeInstancesvaryingNode instances.
pairCountuint32Node pair count.
nodePairsvaryingNode pairs.
  • Unused floats appear only when version is 1.1f.

Each node instance is:

NameTypeDescription
flagsuint321 for attachment node, 0 for instance node.
nameuint32Node's Node_Name value FLCRC32 (case-sensitive).
parentIdint32Node instance parent id (32768 for none).
refIdint32Node instance id.
  • CRC pointing to a node in node library CRC of "Node_Name" parameter.
  • Node instance indices start with 1.
  • Order of node instances in effect is used for draw order.

Each node pair is:

NameTypeDescription
sourceIdint32Pair source node instance (emitter/appearance).
targetIdint32Pair target node instance (appearance/field).

Alchemy Node Library

Node library is a collection of node archetypes. Nodes have type property describing its behavior and list of properties, some of which are fixed values and some are animated.

NameTypeDescription
versionfloat32Version (1.0 or 1.1).
nodeCountuint32Node count.
nodesvaryingNode archetype.

Individual node archetype contains:

NameTypeDescription
nameastringNode type (ex.: "FxBasicAppearance").
propertiesvaryingNode properties.
  • Read node properties until property type is 0.

Each property:

NameTypeDescription
typeuint16Property value type.
nameuint32FLCRC32 of property name (case-sensitive).
datavaryingProperty data based on type.

Type is:

ValueNameAnimated
0x001BooleanNo
0x002IntegerNo
0x003FloatNo
0x103StringNo
0x104BlendingNo
0x105TransformYes
0x200FloatYes
0x201ColorYes
0x202CurveYes

Boolean (0x1 or 0x8001)

  • Contains no data, true/false is determined by most significant bit, i.e. 0x1 is false and 0x8001 is true.

Integer (0x2)

NameTypeDescription
valueint32Signed integer number value.

Float (0x3)

NameTypeDescription
valuefloatFloat point number value.

String (0x103)

NameTypeDescription
valueastringString value.

Color blending (0x104)

NameTypeDescription
sourceuint32Blending source mode.
targetuint32Blending target mode (destination).

Possible values for source and target are:

ValueNameFactor
1D3DBLEND_ZERO0, 0, 0, 0
2D3DBLEND_ONE1, 1, 1, 1
3D3DBLEND_SRCCOLORRs, Gs, Bs, As
4D3DBLEND_INVSRCCOLOR1 - Rs, 1 - Gs, 1 - Bs, 1 - As
5D3DBLEND_SRCALPHAAs, As, As, As
6D3DBLEND_INVSRCALPHA1 - As, 1 - As, 1 - As, 1 - As
7D3DBLEND_DESTALPHAAd, Ad, Ad, Ad
8D3DBLEND_INVDESTALPHA1 - Ad, 1 - Ad, 1 - Ad, 1 - Ad
9D3DBLEND_DESTCOLORRd, Gd, Bd, Ad
10D3DBLEND_INVDESTCOLOR1 - Rd, 1 - Gd, 1 - Bd, 1 - Ad
11D3DBLEND_SRCALPHASATf, f, f, 1 (f = min(As, 1 - Ad))

Transform (0x105)

NameTypeDescription
flagsuint32
translatecurve[3]Translation animation.
rotatecurve[3]Rotation animation.
scalecurve[3]Scale animation.
  • Curve type is animated curve structure.
  • If most significant byte in flags is 0 skip translate/rotate/scale altogether.

Animated float (0x200)

NameTypeDescription
easinguint8Blending value easing type.
keyframeCountuint8Blending keyframe count (1 or more).
keyframesvaryingBlending keyframes.

Each blending parameter keyframe:

NameTypeDescription
keyfloatParameter key.
easinguint8Value easing type.
keyframeCountuint8Value keyframe count (1 or more).
keyframesvaryingValue keyframes.

Each value keyframe:

NameTypeDescription
keyfloatKeyframe key.
valuefloatKeyframe number value.
  • Typically animated float key is relative (0.0 to 1.0).

Animated color (0x201)

NameTypeDescription
easinguint8Blending value easing type.
keyframeCountuint8Blending keyframe count (1 or more).
keyframesvaryingBlending keyframes.

Each blending parameter keyframe:

NameTypeDescription
keyfloatParameter key.
easinguint8Value easing type.
keyframeCountuint8Value keyframe count (1 or more).
keyframesvaryingValue keyframes.

Each value keyframe:

NameTypeDescription
keyfloatKeyframe key.
valuefloat[3]Keyframe color value (RGB).
  • Typically animated color key is relative (0.0 to 1.0).

Animated curve (0x202)

NameTypeDescription
easinguint8Blending value easing type.
keyframeCountuint8Blending keyframe count (1 or more).
keyframesvarying

Each blending parameter keyframe:

NameTypeDescription
keyfloatParameter key.
defaultValuefloatDefault value.
wrapFlagsuint16Wrapping flags for out of bounds keys.
keyframeCountuint16Keyframe count (0 or more).
keyframesvaryingValue keyframes.

Each value keyframe:

NameTypeDescription
keyfloatKeyframe key.
valuefloatKeyframe value.
valueOutfloatKeyframe outgoing value.
valueInfloatKeyframe incoming value.
  • Typically animated curve key is time (seconds).

Easing types

ValueDescription
1Linear.
2Ease in.
3Ease out.
4Ease both.
5Step.

Wrap flags

Determine what happens for out of bounds values.

ValueDescription
0x0001Repeat before.
0x0002Mirror before.
0x0004Clamp before.
0x0010Repeat after.
0x0020Mirror after.
0x0040Clamp after.

Evaluating animated curve value

/**
* Evaluate curve value between keyframes.
* @param w Transition state between keyframes
* @param a Start keyframe value
* @param b End keyframe value
* @param d Delta between start and end keyframe keys
* @returns
*/
mixCurve(w: number, a: Vector3, b: Vector3, d: number) {
const { x: ax, z: av } = a;
const { x: bx, y: bv } = b;

d *= .5;

const a0 = ax + av * d;
const b0 = bx - bv * d;

const a1 = lerp(w, ax, a0);
const b1 = lerp(w, a0, bx);

const a2 = lerp(w, ax, b0);
const b2 = lerp(w, b0, bx);

const a3 = lerp(w, a1, a2);
const b3 = lerp(w, b1, b2);

return lerp(w, a3, b3);
}
  • lerp is a generic linear interpolation function.