CRD Argument Type

Many effects arguments are a CRD type of argument. This stands for ''Continuous Random Distribution'', and is used to assign a variable argument. In other words, the argument's value is not fixed, but is determined at the time the property of an instance of an object first needs it. This allows effects to have a controlled randomness to them: a variable speed and direction for where various bits fly, etc.

A CRD always has four sub-arguments, e.g.:

  CRD_NONE/3/0/0
The first argument says what sort of distribution will happen with the numbers that follow, and the next two arguments are how to vary these numbers. The last argument is called symmetry, and can affect any of the distributions; it will be explained later.

The meaning of the second and third arguments, which are always numbers, varies depending on the type of distribution property specified. The four types for this first argument are:

  • CRD_NONE - do not vary the argument at all, just return the first number.
  • CRD_UNIFORM - uniform random distribution, between the two numbers specified.
  • CRD_EXPONENTIAL - exponential drop off, first number specifies the mean (average).
  • CRD_NORMAL - normal distribution, the first number is the mean, the second the variance.

So these first three arguments compute a random number. The final, fourth argument is a boolean, and can affect the sign of this computed number. Specifically, if this argument is 1 (true), then there is a 50/50 chance that the computed number will be negated. If 0 (false), no negation "coin-flip" takes place.

Some examples:

  ObjectTemplate.TimeToLive CRD_NONE/240/0/0
For the exppack, the time to live before it blows up by itself is always 240 seconds. This sort of CRD can be directly replaced by the number itself, e.g. on the ships the landing craft TimeToLive property is set to 30, even though this property's argument is normally a CRD.

  ObjectTemplate.TimeToLive CRD_UNIFORM/2/4/0
For depth charges, the time to live before it blows up by itself is between 2 and 4 seconds.

  ObjectTemplate.rotationalSpeedInDof CRD_EXPONENTIAL/-20/0/1
The exponential distribution basically gives a distribution curve that drops off sharply and then levels out. It is computed by -mean*ln( random(0,1) ). In other words, a random number between 0 and 1 (not including 0 or 1) is generated, the natural logarithm of this number is computed, and the result is multiplied by the negative of the mean (the average), the second argument (and first number) passed in. For example, if the random number generated was 0.1, the natural log is -2.3, so since the mean was -20, the final number returned would be -(-20)*-2.3 = -46. Since the symmetric flag, the last argument, is set to 1 (true), there is a 50/50 chance that this result will be negated, i.e. be returned as 46 instead of -46.

NOTE: this distribution is often misused in the Battlefield code, e.g.

  ObjectTemplate.initRotation CRD_EXPONENTIAL/0/180/1
is a common use. However, this setting actually always returns a value of 0, since that is the mean specified. The "180" argument is ignored.

  ObjectTemplate.timeToLive CRD_NORMAL/2/3.5/0
A normal distribution is a classic bell curve shape. The second argument is the mean, the average value, and the third argument is the variance, how fast the distribution curve drops off into its bell shape. The fourth argument again acts to force symmetry if set, though the bell curve has its own symmetry when the mean is 0.

Variance specifies the range in which about 4/5ths of the numbers generated will fall. In our example, the 2 is the average time to live desired, and a variance of 3.5 means that this value can vary fairly widely; about 4/5ths of the numbers generated will be in the range +3.5 to -3.5 from the mean of 2, i.e. -1.5 to 5.5, with 1/5th of the numbers appearing above and below this range.

If you want to test out this function, here is pseudocode:

    do {
        u1 = getUniform();    // random number between 0 and 1
        v1 = 2*u1 - 1;        // random number between -1 and 1
        u2 = getUniform();    // random number between 0 and 1
        v2 = 2*u2 - 1;        // random number between -1 and 1
        w = (v1)*(v1) + (v2)*(v2);
    } while (w > 1);
    return mean + variance*v1*sqrt((-2*log(w))/w);
where the mean and variance are the first two numbers passed in. The loop finds a point inside a circle of radius one. The resulting values are then used to generate a normal distribution value, which is multiplied by the variance and has the mean added to it.


Go to the All Properties list, All Types list, Class file list, CON file list, or Main scripting page.