cool "leaf" logo
goes here...


IMPORTANT BULLETIN:  Coliseum2 v2.3 available !!
Tutorial 1:  Rail Spiral  By Steve Kemper (Scatster) & Manuel Tran (WarMonger)

By popular demand, the following is the spiral rail code developed for the Coliseum2 Mod
You may use this code in your mods but you must include Manuel Tran and Steve Kemper in your credits.

The spiral rail is a new function to allow you to switch back and forth to the regular rail code.
Add the new function to the end of cg_weapon.c.

//Rail spiral by Steve Kemper and Manuel Tran
CG_SpiralTrail (clientInfo_t *ci, vec3_t start, vec3_t end)
     vec3_t axis[36], move, move2, next_move, vec, temp;
     float  len;
     int    i, j, k, skip;

localEntity_t *le;
     refEntity_t   *re;

     #define RADIUS   9
     #define ROTATION 1
     #define SPACING  5

     //Better line the spiral with the rail run muzzle.
     start[2] -= 4;
     VectorCopy (start, move);

     //Assign vec a vector that represents the rail line.
     VectorSubtract (end, start, vec);

     //Normalizes vec thus making it a directional vector.
     len = VectorNormalize (vec);

     //Assign temp a normalized vector perpendicular to our direction vector.
     PerpendicularVector(temp, vec);

     //We are ultra effecient by knowing that since the spiral will wrap several times
     //along the line while moving foraward, we only have to compute the positions of
     //the dots around the circle only ONCE. We store these in a local array and then
     //simply project each dot forward a little to create the spiral effect.

     //Index 0 represents 0 and 35 = 350 degrees rotation - each dot is 10 degrees apart.

     for (i = 0 ; i < 36; i++)
          RotatePointAroundVector(axis[i], vec, temp, i * 10);

     //***** Core *****
     //We draw the core first.  Since it has a shorter lifespan than the coil itself,
     //if we run out of temp entities while drawing the coil, the temp entity for the
     //core will be the first one "stolen".

     le = CG_AllocLocalEntity();
     re = &le->refEntity;

     le->leType = LE_FADE_RGB;
     le->startTime = cg.time;
     le->endTime = cg.time + 750;
     le->lifeRate = 1.0 / (le->endTime - le->startTime);

     re->shaderTime = cg.time / 1000.0f;
     re->reType = RT_RAIL_CORE;
     re->customShader =;

     VectorCopy(start, re->origin);
     VectorCopy(end, re->oldorigin);

     le->color[0] = ci->color[0] * 0.75;
     le->color[1] = ci->color[1] * 0.75;
     le->color[2] = ci->color[2] * 0.75;
     le->color[3] = 1.0f;

     AxisClear( re->axis );
     //***** End core *****

     //move it a little forward...
     VectorMA(move, 20, vec, move);

     //Copy so it can be re-used.
     VectorCopy(move, next_move);

     //Transform vec so it represents a vector of length SPACING.
     //This represents the line segments along the rail line.

     VectorScale (vec, SPACING, vec);

     //Indicator to let us know when to skip a dot.
     skip = -1;

     //We draw the spiral skipping every other dot. Then we come back and
     //fill in the gaps. That way, if we run out of temp entities, only
     //every other dot will be "stolen" and we will have some remnant of a
     //spiral left. Also, if we know the length is too long (over 2200),
     //then we dont bother to come back to fill in gaps, since there won't
     //be enough temp entities left anyways.

     for (k = (len > 2200); k < 2; k++)
          //Start at 180 degrees
          j = 18;

          for (i = 0; i < len; i += SPACING)
               if (i != skip)
                    skip = i + SPACING;
                    le = CG_AllocLocalEntity();
                    re = &le->refEntity;

                    le->leFlags = LEF_PUFF_DONT_SCALE;
                    le->leType = LE_MOVE_SCALE_FADE;

                    //Lifetime is hardcoded to prevent obscene
                    //numbers from potentially causing problems.

                    le->startTime = cg.time;
                    le->endTime = cg.time + 1200;
                    le->lifeRate = 1.0 / (le->endTime - le->startTime);

                    re->shaderTime = cg.time / 1000.0f;
                    re->reType = RT_SPRITE;
                    re->radius = 1.5;
                    re->customShader =;

                    re->shaderRGBA[0] = ci->color[0] * 255;
                    re->shaderRGBA[1] = ci->color[1] * 255;
                    re->shaderRGBA[2] = ci->color[2] * 255;
                    re->shaderRGBA[3] = 255;
                    le->color[0] = ci->color[0] * 0.75;
                    le->color[1] = ci->color[1] * 0.75;
                    le->color[2] = ci->color[2] * 0.75;
                    le->color[3] = 1.0f;

                    le->pos.trType = TR_LINEAR;
                    le->pos.trTime = cg.time;

                                        //Copy the current position into temp storage.
                    VectorCopy( move, move2);
                    //Project the position along the line outwards at the proper angle.
                    VectorMA(move2, RADIUS , axis[j], move2);
                    //Assign position to temp local entity.
                    VectorCopy(move2, le->pos.trBase);

                    //Set drift speed and direction of the dot.
                    le->pos.trDelta[0] = axis[j][0]*6;
                    le->pos.trDelta[1] = axis[j][1]*6;
                    le->pos.trDelta[2] = axis[j][2]*6;

               //Step forward along the rail line in increment of vec.
               VectorAdd (move, vec, move);

               //Continue to loop through the array as we draw the spiral
               //returning to the first array element, round and round.

               j = j + ROTATION < 36 ? j + ROTATION : (j + ROTATION) % 36;

          //Return to beginning of rail line.
          VectorCopy(next_move, move);
          skip = 0;

}  //End function


You must also declare this new function.  Add the following to cg_local.h.

void CG_SpiralTrail (clientInfo_t *ci, vec3_t start, vec3_t end);


To use the function, seach the client project for calls to CG_RailTrail and replace it with CG_SpiralTrail.


If you should have any ideas on how to improve this function please e-mail me.