1) create a cube, drop in the A) FOLLOW, B) AIM and C) SHOOT scripts.
2) create a sphere, resize it to 0.025x0.025x0.025, drop in the D) GENERIC BULLET SCRIPT (it's made to avoid prim-littering) and pick up your brand new bullet before it selfdeletes
3) put the bullet into the cube
4) click the cube to activate it
------------------------
A) DRONE - FOLLOW
------------------------
// Script based on
//
// the Follower script found at
// http://wiki.secondlife.com/wiki/Follower_%28script%29
//
// and the Break script by TwoPercent Milk, contained into
// Darjay Serf's target dummy.
key target; // Used to store the target avatar's key.
vector pos; // Used to store the current position.
float maxHealth = 100.0; // Used to set health points.
float damage = 10; // Used to set damage value.
float health; // Used to store the remaining health points
default
{
on_rez(integer start_param)
{
llResetScript();
}
// Script is resetted to its default values on object's rezzing
// (state_entry section).
state_entry()
{
pos = llGetPos();
// Used to acquire the current position.
llSleep(0.1);
// Little pause to allow server to make potentially large linked
// object physical.
llSetText("Standby", <1,1,1>, 1);
// Message initially displayed above the object.
}
touch_start(integer total_number)
{
target = llDetectedKey(0);
// Avatars touching the object will be aquired as targets.
llSay(0, "Locked on " + llKey2Name(llDetectedKey(0)));
// On new target acquisition, a confirmation message will be
// sent.
llInstantMessage(llDetectedKey(0),
"Type !die in main chat to delete me."

// Short instruction message is sent to the new target avatar.
llListen(0,"","target","!die"

// Listens on main chat for the target avatar's selfdestruction
// command, which is !die
llSensorRepeat("", "target", AGENT, 20.0, PI, 1.0);
// Look for the touching avatar within 20 metres in 360 degree
// arc every 1 seconds.
llSetStatus(STATUS_PHYSICS, TRUE);
// Object's physics status set to TRUE
// http://lslwiki.net/lslwiki/wakka.php?wakka=STATUS_PHYSICS
health = maxHealth;
// The total health points are resetted to the initial value if
// the object has been hit before being activated by touching it;
// or if the target has changed.
llSetStatus(STATUS_DIE_AT_EDGE, TRUE);
// The drone can not do sim crossing.
// This prevents drones to go into script inactive sims where
// they couldn't selfdelete.
llSetTimerEvent(300);
// Selfdestruction timer is set to 300 seconds (5 minutes).
// This prevents prim littering.
}
sensor(integer total_number)
{
llSetText("Health: " + (string)((integer)health), <1,1,1>, 1);
// Places a text line above the object displaying the available
// health points.
vector pos = llDetectedPos(0);
// Acquires the current target avatar's position
vector offset = <0,0,0> + <llFrand(9) + llFrand(-9),
llFrand(9) + llFrand(-9),
llFrand(4)>;
pos += offset;
// Adds random values to the detected position, in order to
// make the drone keep moving around its target.
llMoveToTarget(pos, 0.4);
// Move to acquired position at selected speed (higher is
// slower).
}
listen(integer channel, string name, key id, string message)
{
if(llToLower(message) == "!die"

{
llSay(0, "/me executing selfdestruction command."

llDie();
// If the selfdestruction command is given, a confirmation
// message will be said and then the drone will selfdelete.
}
}
timer()
{
llSay(0, "/me executing selfdestruction."

llDie();
// If the selfdestruction timer limit is reached, a warning
// message will be said and then the drone will selfdelete.
}
collision_start(integer times)
{
health = health - damage;
// This calculates the remaining health points.
if(health<=0)
{
llRezObject("piece1", pos, <llFrand(9) + llFrand(-9),
llFrand(9) + llFrand(-9),
llFrand(9)>,
ZERO_ROTATION, 0);
// The drone pieces contained into your object are rezzed
// at random positions when no health points are left.
// Be sure that they are temporary prims!
llRezObject("piece2", pos, <llFrand(9) + llFrand(-9),
llFrand(9) + llFrand(-9),
llFrand(9)>,
ZERO_ROTATION, 0);
// Add as more rezzing commands as more pieces you want to
// be rezzed.
llDie();
// Drone selfdeletes.
}
}
}
------------------------
B) DRONE - AIM
------------------------
key target; // Used to store the target avatar's key.
default
{
on_rez(integer param)
{
llResetScript();
// Resets the script to its default values each time the object
// is rezzed.
}
touch_start(integer total_number)
{
target = llDetectedKey(0);
// Avatars touching the object will be aquired as targets.
llSensorRepeat("", "target", AGENT, 20.0, PI, 0.1);
// Scans for the target within 20 metres in 360 degree arc
// every 0.1 seconds. This keeps the object always facing its
// target even while moving.
}
sensor(integer total_number)
{
llLookAt(llDetectedPos(0) + <0.0, 0.0, 0.5>, 0.2, 0.3);
// Makes the object look at the acquired target.
}
}
------------------------
B) DRONE - SHOOT
------------------------
// Script based on:
//
// the Eric Linden's popgun script
// ( Inventory > Library > Objects > popgun )
//
// the Cannon Scripts found at
// http://oz.slinked.net/history/lsl2_reference.htm#_Toc43275567
float SPEED = 75; // Speed of bullets in meters/sec.
float DELAY = 0.25; // Delay between shots to impose.
vector pos; // Used to store the position of the bullets to be shot.
vector dir; // Used to store the direction of the bullets to be shot.
rotation rot; // Used to store the rotation of the bullets to be shot.
key target; // Used to store the target avatar's key.
// Follows the function used to fire.
fire()
{
rot = llGetRot();
pos = llGetPos();
dir = llRot2Up(rot);
pos += dir;
dir *= SPEED;
pos.z += 0.0; // This value is used to slightly correct the
// final Z position of the bullet to be shot,
// in few words it determines a little vertical
// shift of the aim point from the crosshair.
llRezObject("bullet", pos, dir, <0,0,0,1>, 0);
// This rezzes the prim-bullet contained into your weapon,
// giving it all the needed values (position, direction,
// rotation).
// Be sure that bullets are temporary prims to avoid prim littering!
llSleep(DELAY);
// This imposes a short delay between shots.
}
default
{
on_rez(integer param)
{
llResetScript();
}
// Script is resetted to its default values on object's rezzing
// (state_entry section).
touch_start(integer total_number)
{
target = llDetectedKey(0);
// Avatars touching the object will be aquired as targets.
llListen(0,"","target","!on"

// Listens on main chat for the target avatar's activation
// command, which is !on
llListen(0,"","target","!off"

// Listens on main chat for the target avatar's deactivation
// command, which is !off
llInstantMessage(llDetectedKey(0),
"Type !on or !off in main chat to activate/deactivate the gun."

// Short instructions message is sent to the acquired target.
}
listen(integer channel, string name, key id, string message)
{
if(llToLower(message) == "!on"

{
llSay(0, "Gun activated."

llSetTimerEvent(2);
// If the activation command is given, a confirmation
// message will be said and then the program will be
// executed every 2 seconds.
}
if(llToLower(message) == "!off"

{
llSay(0, "Gun deactivated."

llSetTimerEvent(0);
// If the deactivation command is given, a confirmation
// message will be said and then the program will be
// stopped.
}
}
timer()
{
integer randNumber = (integer)llFrand(4);
// Randomizes the value used to determine how many times the
// fire() function will be executed.
if(randNumber == 0)
{
fire();
}
// If the random value is 0 then the fire() function will be
// executed once.
if(randNumber == 1)
{
fire();
fire();
}
// If the random value is 1 then the fire() function will be
// executed twice.
if(randNumber == 2)
{
fire();
fire();
fire();
}
// And so on.
if(randNumber == 3)
{
fire();
fire();
fire();
fire();
}
// And so on.
}
}
------------------------
D) GENERIC ANTI PRIM-LITTERING BULLET
------------------------
default
{
on_rez(integer a)
{
llResetScript();
}
// Script is resetted to its default values on object's rezzing
// (state_entry section).
state_entry()
{
llSetTimerEvent(7);
// Timer event set on 7 seconds.
llSetStatus(STATUS_PHYSICS, TRUE);
// Object's physics status set to TRUE
// http://lslwiki.net/lslwiki/wakka.php?wakka=STATUS_PHYSICS
llSetStatus(STATUS_DIE_AT_EDGE, FALSE);
// Object can do sim crossing.
// Set to TRUE to make it selfdelete on sim crossing.
llSetPrimitiveParams(
[PRIM_TEMP_ON_REZ, TRUE,
PRIM_MATERIAL, PRIM_MATERIAL_METAL]
);
// Object is set to be a temporary prim (if not yet): it will
// selfdelete after 60/70 seconds in sims where scripts are
// disabled. Object's material is set to METAL.
// http://wiki.secondlife.com/wiki/PRIM_MATERIAL
llSetBuoyancy(1);
// Gravity's effect on the object.
// 1 means less or more "no fall and no rise".
// http://wiki.secondlife.com/wiki/LlSetBuoyancy
llSetDamage(15);
// In damage active sims, the object will do 15% of damage
// when colliding with avatars.
// http://wiki.secondlife.com/wiki/LlSetDamage
llPlaySound("4dd615aa-d35d-de4e-2a6f-ee36af0631f1", 1);
// This plays at full volume a laser shot sound.
// Change the UUID between quotes to play another one.
// http://wiki.secondlife.com/wiki/LlPlaySound
}
collision_start(integer a)
{
llDie();
}
// Object selfdeletes on avatar or object collision.
touch_start(integer a)
{
llDie();
}
// Object selfdeletes on touch.
land_collision_start(vector a)
{
llDie();
}
// Object selfdeletes on land collision.
timer()
{
llDie();
}
// Object selfdeletes on timer event.
}