// Sonic Screwdriver portal generator. Copyright (c) 2009 by Cheshyr Pontchartrain.

string gShotSound = "6d940603-4f66-87e3-9d1d-e87e29422782";
integer CHANNEL = -53302;

string gAnim = "aim_r_handgun";
integer gGrip = ATTACH_RHAND;
string gGripMessage = "This is a right-handed object.";
integer gArmed;
vector gAimOffsetConstant = <0.0, 0.0, 0.84>;
vector gAimOffset;

integer gEnableSound = TRUE;
integer attached = FALSE;
integer permissions = FALSE;

vector color;
vector centerpos;
vector fwd;
vector pos;
rotation rot;
key holder;

particles(key target)
{
llSetPrimitiveParams([ PRIM_GLOW, ALL_SIDES, 0.15, PRIM_FULLBRIGHT, ALL_SIDES, TRUE, PRIM_POINT_LIGHT, TRUE, color, 1.0, 5.0, 0.25 ]);
llParticleSystem([
PSYS_PART_FLAGS, PSYS_PART_EMISSIVE_MASK | PSYS_PART_INTERP_COLOR_MASK | PSYS_PART_INTERP_SCALE_MASK | PSYS_PART_TARGET_POS_MASK,
PSYS_PART_MAX_AGE, 5.0,
PSYS_PART_START_COLOR, <1.00000, 1.00000, 1.00000>,
PSYS_PART_END_COLOR, color,
PSYS_PART_START_SCALE, <0.20000, 0.20000, 0.00000>,
PSYS_PART_END_SCALE, <3.50000, 3.50000, 0.00000>,
PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_ANGLE_CONE,
PSYS_SRC_BURST_RATE,0.050000,
PSYS_SRC_ACCEL,ZERO_VECTOR,
PSYS_SRC_BURST_PART_COUNT,3,
PSYS_SRC_BURST_RADIUS,0.000000,
PSYS_SRC_BURST_SPEED_MIN,0.400000,
PSYS_SRC_BURST_SPEED_MAX,0.400000,
PSYS_SRC_INNERANGLE,0.017453,
PSYS_SRC_OUTERANGLE,0.034907,
PSYS_SRC_OMEGA,ZERO_VECTOR,
PSYS_SRC_MAX_AGE,0.000000,
PSYS_PART_START_ALPHA,1.000000,
PSYS_PART_END_ALPHA,1.000000,
PSYS_SRC_TEXTURE, "50eb6e84-815e-1683-6ca2-b6d6805b0bec",
PSYS_SRC_TARGET_KEY, target ]);
}

particles_off()
{
llParticleSystem([]);
llSetPrimitiveParams([ PRIM_GLOW, ALL_SIDES, 0.05, PRIM_FULLBRIGHT, ALL_SIDES, FALSE, PRIM_POINT_LIGHT, FALSE, color, 0.8, 5.0, 0.5 ]);
}

getPerms()
{
integer perms = llGetPermissions()
| PERMISSION_TAKE_CONTROLS
| PERMISSION_TRIGGER_ANIMATION
| PERMISSION_ATTACH;
llRequestPermissions(llGetOwner(), perms);
}

arm()
{
integer perm = PERMISSION_TAKE_CONTROLS | PERMISSION_TRIGGER_ANIMATION;
if ((llGetPermissions() & perm) != perm ) {
getPerms();
} else {
llTakeControls(CONTROL_ML_LBUTTON, TRUE, FALSE);
gArmed = TRUE;
}
}

disarm()
{
if (llGetAgentSize(llGetPermissionsKey()) != ZERO_VECTOR) {
llStopAnimation("hold_R_handgun");
llStopAnimation("aim_R_handgun");
}

llReleaseControls();
gArmed = FALSE;
}

default
{
on_rez(integer param)
{
llResetScript();
}

state_entry()
{
color = llGetColor(1);
llListen(CHANNEL, "", NULL_KEY, "STOP_PART");
getPerms();
}

run_time_permissions(integer perms)
{
if (perms & (PERMISSION_TAKE_CONTROLS
| PERMISSION_TRIGGER_ANIMATION
| PERMISSION_ATTACH)) {
if (!llGetAttached()) {
llAttachToAvatar(gGrip);

} else if (llGetAttached() != gGrip) {
llOwnerSay(gGripMessage);
llDetachFromAvatar();

} else {
arm();
}
} else {
llOwnerSay("Insufficient permissions");
if (llGetAttached()) llDetachFromAvatar();
}
}

attach(key avatar)
{
//
// If attached/detached from agent, change behavior
//
if (avatar != NULL_KEY) {
getPerms();

} else {
disarm();
}
}

object_rez(key id)
{
if (llKey2Name(id) == "TOP") {
particles(id);
llSensorRepeat("", id, SCRIPTED, 32.0, PI, 1.0);
}
}

listen(integer channel, string name, key id, string message)
{
if (llGetOwner() != llGetOwnerKey(id)) return;

if (llGetAgentSize(llGetPermissionsKey()) != ZERO_VECTOR) {
llStopAnimation("hold_R_handgun");
llStopAnimation("aim_R_handgun");
}

llSensorRemove();
particles_off();
}

control(key avatar, integer levels, integer edges)
{
// mouse press
if ((levels & CONTROL_ML_LBUTTON) && (edges & CONTROL_ML_LBUTTON)) {
}

// mouse release
if (!(levels & CONTROL_ML_LBUTTON) && (edges & CONTROL_ML_LBUTTON)) {
if (gEnableSound) llTriggerSound(gShotSound, 1.0);
llStartAnimation(gAnim);

rotation rot = llGetRot();
vector aim = llRot2Fwd(rot);
vector pos = llGetPos() + (aim * 2.0);
pos.z += 0.75; // Correct to eye point

llRezObject("TOP", pos + (<0.0,0.0,0.5> * rot), ZERO_VECTOR, rot, 1);
llRezObject("LEFT", pos, ZERO_VECTOR, rot, 1);
llRezObject("RIGHT", pos + (<0.0,-0.5,0.0> * rot), ZERO_VECTOR, rot, 1);
}

// mouse down
if ((levels & CONTROL_ML_LBUTTON) && !(edges & CONTROL_ML_LBUTTON)) {
// Placeholder should we want to adjust distance based on how long the mouse is held down.
}
}

changed(integer change)
{
if (change & CHANGED_COLOR)
color = llGetColor(1);
}

sensor(integer num_detected)
{
// Do nothing
}

no_sensor()
{
if (llGetAgentSize(llGetPermissionsKey()) != ZERO_VECTOR) {
llStopAnimation("hold_R_handgun");
llStopAnimation("aim_R_handgun");
}

llSensorRemove();
particles_off();
}
}