Title: Projectile Spread. Purpose: I came to a point where I wanted to add variability to the weapon firing based on range. A simple server-side addition randomly selects the trajectory based on a cone from the player's eye. Discussion: This system projects a circle along the player's view to the maximum range of the weapon. It randomly selects an offset from center and a direction from center. This is then scaled to the eye vector and normalized for projectile use. Comments: There are many ways to determine the diameter of the circle, whether it be constant, as in my example, or based on the players speed or position. I have shown it as an extension of the weapon object, but it can easily be made into a function that is called by all weapons. Development Environment: August 2006 Head 1.4 Win32 Single and Multi Player Implementation: ScriptFile: /server/scripts/crossbow.cs function CrossbowImage::onFire(%this, %obj, %slot) { %projectile = %this.projectile; // Decrement inventory ammo. The image's ammo state is update // automatically by the ammo inventory hooks. %obj.decInventory(%this.ammo,1); // Determin initial projectile velocity based on the // gun's muzzle point and the object's current velocity %muzzleVector = %obj.getMuzzleVector(%slot); //------- Projectile Spread ------- // These two variables can come from the datablock, a player function, or both, or static values. %maxRange = 200; // game units %spread = 4; // radius of circle at max range in game units (this decreases as the target is closer) %randDist = getRandom(0,%spread*1000) / 1000; // random distance from center %randDir = getRandom(0,62831) / 1000; // random direction on circle %rvar = mSin(%randDir) * %randDist; // horizontal distance from center %uvar = mCos(%randDir) * %randDist; // vertical distance from center %muzzleTransform = %obj.getSlotTransform(%slot); %aa = getWords(%muzzleTransform, 3, 6); %tmat = VectorOrthoBasis(%aa); %rv = getWords(%tmat, 0, 2); // Right Vector %fv = getWords(%tmat, 3, 5); // Forward Vector %uv = getWords(%tmat, 6, 8); // Up Vector %roffset = VectorScale(%rv, %rvar); // scale horizontal vector by horizontal distance %uoffset = VectorScale(%uv, %uvar); // scale vertical vector by vertical distance // Combine for final vector %muzzleVector = VectorScale(%muzzleVector, %maxRange); %muzzleVector = VectorAdd(%muzzleVector, %roffset); %muzzleVector = VectorAdd(%muzzleVector, %uoffset); %muzzleVector = VectorNormalize(%muzzleVector); //----- End Projectile Spread ----- %objectVelocity = %obj.getVelocity(); %muzzleVelocity = VectorAdd( VectorScale(%muzzleVector, %projectile.muzzleVelocity), VectorScale(%objectVelocity, %projectile.velInheritFactor)); // Create the projectile object %p = new (%this.projectileType)() { dataBlock = %projectile; initialVelocity = %muzzleVelocity; initialPosition = %obj.getMuzzlePoint(%slot); sourceObject = %obj; sourceSlot = %slot; client = %obj.client; }; MissionCleanup.add(%p); return %p; } Credits: Derk Adams - adamsderk@hotmail.com