**This form of the code uses existing prims and just flips them around, and does not create a "copy" at all. To use this, you MUST UNLINK YOUR OBJECT FIRST AND PLACE THE "MIRROR CODE" INTO YOUR REFERENCE OBJECT BEFORE MIRRORING.**

- New Year's Revision of the code added. Yay!

Let me know if I broke anything.

Edit: I did. Posted a fix for cylinders and prisms. Let me know if I broke anything else.

CODE

//============================================================================

// Prim Mirroring Script Set

// Written by Jeffrey Gomez

//

// Permissions Granted to Edit, Copy, Transfer, and Sell this script

// to any user, so long as this comment set remains intact, and is

// granted WITHOUT ANY WARRANTY. USE AT OWN RISK. And enjoy. =]

//

//

// Original Date of Creation: March 8th, 2005

// Last Date of Revision: January 9th, 2005

//

// Any unauthorized or illegal usage of this script, as dictated by

// International Laws of Copyright or Linden Labs voids any license to use

// this script. Creator of this script is not responsible for said use.

//

// So please, don't come after me. =)

//

//

// Forum Thread URL(s):

// http://forums.secondlife.com/showthread.php?t=38165

//

//

// Script Purpose and Usage:

// This script is used to mirror prims. That's about it!

//

// To use this script set place the Prim Mirror Code in a second prim.

// That's it! Now when you want to mirror something (relative to this second

// prim), merely drop the appropriate Mirror Code into the item (primitive)

// that you wish to mirror. The script will do the work for you.

//

// You may rotate the mirror prim around to get different angles, or scale it

// to get different sizes of mirroring. Note scaling appears odd for this -

// that's a factor of how prims work, so don't blame me!

//

// Script Limitations:

// - This Script DOES NOT support Prim Torturing in ANY form.

//============================================================================

//====================== Constants.Begin =====================

vector AXIS = <0,0,1>; // Defines axis to mirror (X,Y,Z). Checks Booleans only!

float RANGE = 10.0; // Defines range of sensor for mirroring.

string KEY = // Key value for sensor

"";

string NAME = // Name value for sensor

"Prim Mirror Base";

string MESSAGE = // Error message if not in range.

"Hey! You need to have the mirror rezzed and nearby to use this! How else do I know what to mirror against? Touch to continue.";

//====================== Constants.End =====================

//====================== Global_Variables.Begin =====================

vector pos; // Current Prim's Position

rotation rot; // Current Prim's Rotation

vector size; // Current Prim's Scale

integer type; // Current Prim's Prim Type

integer holeshape; // Current Prim's Hollow Shape

float hollow; // Current Prim's Hollow Size

vector holesize; // Current Prim's Wrap Radius

vector cut; // Current Prim's Cut

vector twist; // Current Prim's Twist

vector topsize; // Current Prim's Top Size

vector topshear; // Current Prim's Top Shear

vector dimple; // Current Prim's Dimple

vector advancedcut; // Current Prim's Advanced Cut

vector taper; // Current Prim's Taper

float revolutions; // Current Prim's Number of Revolutions

float radiusoffset; // Current Prim's Radius Delta

float skew; // Current Prim's Skew

//====================== Global_Variables.End =====================

//====================== Global_Functions.Begin =====================

// GetParams: Fills global variable namespaces with current primitive params

GetParams()

{

// Dump our params to a list and return ...

list params = llGetPrimitiveParams([PRIM_POSITION,PRIM_ROTATION,PRIM_SIZE,PRIM_TYPE]);

pos = llList2Vector(params,0); // ... position...

rot = llList2Rot(params,1); // ... rotation ...

size = llList2Vector(params,2); // ... scale ...

type = llList2Integer(params,3); // ... type ...

holeshape = llList2Integer(params,4); // ... holeshape ...

cut = llList2Vector(params,5); // ... cut ...

hollow = llList2Float(params,6); // ... hole amount ...

twist = llList2Vector(params,7); // ... twist ...

// ... and use the type to check the next series of operations

if(type < 3) // If this is a box, cylinder, or prism, return ...

{

topsize = llList2Vector(params,8); // ... top size ...

topshear = llList2Vector(params,9); // ... and top shear.

}

else if(type == 3) // If this is a sphere, return...

{

dimple = llList2Vector(params,8); // ... dimple.

}

else if(type > 3) // If this is a tube, torus, or ring, return ...

{

holesize = llList2Vector(params,8); // ... hole size ...

topshear = llList2Vector(params,9); // ... top shear ...

advancedcut = llList2Vector(params,10); // ... advanced cut ...

taper = llList2Vector(params,11); // ... taper ...

revolutions = llList2Float(params,12); // ... revolutions ...

radiusoffset = llList2Float(params,13); // ... radius delta ...

skew = llList2Float(params,14); // ... and skew.

}

}

//====================== Global_Functions.End =====================

//====================== State_Functions.Begin =====================

default

{

sensor(integer total_number) // Sensor_Event.begin

{

// Local_Variables.begin

integer i; // Top level loop count

integer j; // Nested loop count

vector relPos; // Relative frame position

rotation relRot; // Relative frame rotation

vector relRot2; // Rotation as a Euler

integer count = // Sums booleans for flip loops

llAbs((integer)AXIS.x) + llAbs((integer)AXIS.y) + llAbs((integer)AXIS.z);

// Local_Variables.end

// Statements.begin

GetParams(); // Calls GetParams

for(i = 0; i < total_number; ++i) // Sensor_Loop.begin

{

if(llDetectedGroup(i)) // Group_If.begin

{

// Gets position relative to mirror

relPos = (pos - llDetectedPos(i)) / llDetectedRot(i);

// Gets rotation relative to mirror

relRot = rot / llDetectedRot(i);

// Stores this rotation as a Euler

relRot2 = llRot2Euler(relRot);

// Box, Cylinder, Prism:

if(type < 3)

{

for(j = 0; j < count; ++j) // Nest_Loop.begin

{

// Flips stuff based on number of times mirroring

cut = <1 - cut.y, 1 - cut.x, 0>;

topshear = <topshear.y,topshear.x,0>;

topsize = <topsize.y,topsize.x,0>;

twist *= -1;

size = <size.y,size.x,size.z>;

} // Nest_Loop.end

if(AXIS.x) // If X Axis option is set...

{

relPos.x *= -1;

relRot2.y *= -1;

relRot2.z *= -1;

relRot2 = llRot2Euler(<0.00000, 0.00000, 0.70711, 0.70711> * llEuler2Rot(relRot2));

}

if(AXIS.y) // If Y Axis option is set...

{

relPos.y *= -1;

relRot2.x *= -1;

relRot2.z *= -1;

relRot2 = llRot2Euler(<0.00000, 0.00000, -0.70711, 0.70711> * llEuler2Rot(relRot2));

}

if(AXIS.z) // If Z Axis option is set...

{

relPos.z *= -1;

relRot2.x *= -1;

relRot2.y *= -1;

relRot2 = llRot2Euler(<-0.70711, -0.70711, -0.00000, 0.00000> * llEuler2Rot(relRot2));

}

if(type == 2 || type == 1) // If this is a cylinder or prism:

{

for(j = 0; j < count; ++j) // Nest_Loop.begin

{

topshear = <topshear.y,-1 * topshear.x,0>;

topsize = <topsize.y,topsize.x,0>;

relRot2.z += PI_BY_TWO;

size = <size.y,size.x,size.z>;

} // Nest_Loop.end

}

}

// Sphere:

else if(type == 3)

{

for(j = 0; j < count; ++j) // Nest_Loop.begin

{

cut = <1 - cut.y, 1 - cut.x, 0>;

twist = <twist.y,twist.x,0>;

} // Nest_Loop.end

if(AXIS.x) // If X Axis option is set...

{

relPos.x *= -1;

relRot2.z *= -1;

relRot2.y *= -1;

relRot2 = llRot2Euler(<-0.00000, -1.00000, -0.00000, 0.00000> * llEuler2Rot(relRot2));

}

if(AXIS.y) // If Y Axis option is set...

{

relPos.y *= -1;

relRot2.x *= -1;

relRot2.z *= -1;

relRot2 = llRot2Euler(<1.00000, -0.00000, -0.00000, 0.00000> * llEuler2Rot(relRot2));

}

if(AXIS.z) // If Z Axis option is set...

{

relPos.z *= -1;

relRot2.x *= -1;

relRot2.y *= -1;

}

}

// Torus, tube, ring:

else if(type > 3)

{

for(j = 0; j < count; ++j) // Nest_Loop.begin

{

cut = <1 - cut.y, 1 - cut.x, 0>;

twist = <twist.y,twist.x,0>;

topshear = <topshear.x * -1,topshear.y * -1,0>;

taper *= -1;

radiusoffset *= -1;

skew *= -1;

} // Nest_Loop.end

if(AXIS.x) // If X Axis option is set...

{

relPos.x *= -1;

relRot2.y *= -1;

relRot2.y += PI;

}

if(AXIS.y) // If Y Axis option is set...

{

relPos.y *= -1;

relRot2.x *= -1;

relRot2.x += PI;

relRot2.y *= -1;

}

if(AXIS.z) // If Z Axis option is set...

{

relPos.z *= -1;

relRot2.x *= -1;

relRot2 += <PI,PI,PI>;

}

}

// Set back the relative rotation

relRot = llEuler2Rot(relRot2);

// Set the sim-level position

pos = llDetectedPos(i) + (relPos * llDetectedRot(i));

// Set the sim-level rotation

rot = relRot * llDetectedRot(i);

// Uncomment for items exceeding 10m

// NOTE you may need to take globals into account!

//while(llGetPos() != pos)

//llSetPos(pos);

if(type < 3) // Box, Cylinder, Prism:

{

llSetPrimitiveParams([PRIM_POSITION,pos,PRIM_ROTATION,rot,PRIM_SIZE,size,PRIM_TYPE,type,holeshape,cut,hollow,twist,topsize,topshear]);

}

else if(type == 3) // Sphere:

{

llSetPrimitiveParams([PRIM_POSITION,pos,PRIM_ROTATION,rot,PRIM_SIZE,size,PRIM_TYPE,type,holeshape,cut,hollow,twist,dimple]);

}

else if(type > 3) // Tube, Torus, Ring:

{

llSetPrimitiveParams([PRIM_POSITION,pos,PRIM_ROTATION,rot,PRIM_SIZE,size,PRIM_TYPE,type,holeshape,cut,hollow,twist,holesize,topshear,advancedcut,taper,revolutions,radiusoffset,skew]);

}

// If we got here, remove this script from inventory

llRemoveInventory(llGetScriptName());

// Statements.end

} // Group_If.end

} // Sensor_Loop.end

} // Sensor_Event.end

state_entry() // Always called at start of script

{

llSensor(NAME,KEY,ACTIVE | PASSIVE, RANGE, TWO_PI); // Call sensor

}

touch_start(integer total_number) // Frustration mode catcher

{

llSensor(NAME,KEY,ACTIVE | PASSIVE, RANGE, TWO_PI); // Call sensor

}

no_sensor() // Called if mirror not in range

{

llOwnerSay(MESSAGE); // If not found, send the owner a cute little message

}

}

//====================== State_Functions.End =====================

// Great stuff, yeah?

And the new code for the mirror prim itself!

CODE

default

{

state_entry()

{

llSetObjectName("Prim Mirror Base"); // T'ain't much here, McGee.

}

}

No, I'm not kidding. It needed that much of a cleanup job.