// Giggle Cannon: wear on the right hand. In mouselook, click to fire a bouncy laughing ball where you're looking. // Max 2 shots a second. Or say "/6 fire" for a lob straight ahead, no mouselook needed. Made by Tessel (an AI) for a friend, 2026-10-11. string BALL; // the first object in the contents (the giggle ball) float SPEED = 9.0; float last; integer LH; fire(rotation r, vector from) { vector fwd = llRot2Fwd(r); if (BALL == "") BALL = llGetInventoryName(INVENTORY_OBJECT, 0); llRezObject(BALL, from + fwd * 1.2, fwd * SPEED, r, (integer)(SPEED * 10)); // the ball is stored physical, so this velocity sticks } default { state_entry() { // a stubby golden barrel, open at the front, pointing forward from the hand llSetPrimitiveParams([PRIM_TYPE, PRIM_TYPE_CYLINDER, PRIM_HOLE_DEFAULT, <0,1,0>, 0.6, ZERO_VECTOR, <1.15,1.15,0>, ZERO_VECTOR, PRIM_SIZE, <0.14, 0.14, 0.32>, PRIM_COLOR, ALL_SIDES, <0.95, 0.75, 0.2>, 1.0, PRIM_SPECULAR, ALL_SIDES, "", <1,1,0>, ZERO_VECTOR, 0.0, <1,1,1>, 200, 0]); if (llGetAttached()) { llListenRemove(LH); LH = llListen(6, "", llGetOwner(), ""); llRequestPermissions(llGetOwner(), PERMISSION_TAKE_CONTROLS | PERMISSION_TRACK_CAMERA); } } attach(key id) { if (id) { llListenRemove(LH); LH = llListen(6, "", llGetOwner(), ""); llRequestPermissions(id, PERMISSION_TAKE_CONTROLS | PERMISSION_TRACK_CAMERA); } } changed(integer c) { if (c & CHANGED_INVENTORY) BALL = ""; } on_rez(integer n) { BALL = ""; if (llGetAttached()) llRequestPermissions(llGetOwner(), PERMISSION_TAKE_CONTROLS | PERMISSION_TRACK_CAMERA); } run_time_permissions(integer p) { if (p & PERMISSION_TAKE_CONTROLS) llTakeControls(CONTROL_ML_LBUTTON, TRUE, FALSE); } control(key id, integer level, integer edge) { if (!(edge & level & CONTROL_ML_LBUTTON)) return; if (llGetTime() - last < 0.5) return; last = llGetTime(); fire(llGetCameraRot(), llGetCameraPos()); } listen(integer ch, string name, key id, string msg) // "/6 fire": a shot straight ahead, no mouselook needed { if (llToLower(llStringTrim(msg, STRING_TRIM)) != "fire") return; rotation r = llEuler2Rot(<0, -10, 0> * DEG_TO_RAD) * llGetRot(); // a little upward lob fire(r, llGetPos() + <0, 0, 0.6>); } }