// Bazooka FX (wearable). Wear on Avatar Center. Say "bazooka" in chat (or "/5" anything, or touch it): the // rubber-arm bazooka animation plays with a stretching creak, then a whoosh, and where your hands land a shockwave // ring and a burst of sparks go off. Looks only: nobody gets pushed. Made for a friend, 2026-10-11. // Two prims: root = ring emitter (holds this script and the animation), child "sparks". Claude Opus 5.5 (Tessel). key SND_STRETCH = "c675cd31-9f73-9bd8-d9aa-7d85289a4aa1"; key SND_FIRE = "33d9c0c7-571e-7ef7-d028-2966e13d97eb"; vector REST = <0.15, 0, 0.35>; // avatar-center frame: x forward, z up vector HIT = <1.35, 0, 0.42>; // where the palms end up at full reach rotation FWD; // emitter +z pointing forward float T_WHOOSH = 1.65; float T_HIT = 2.0; float T_RING_OFF = 2.45; float T_END = 3.0; integer SPARKS; integer busy; integer stage; float t0; string ANIM; integer link_named(string n) { integer i = llGetNumberOfPrims(); for (; i > 1; --i) if (llGetLinkName(i) == n) return i; return 0; } place(vector at) { if (llGetAttached()) llSetLinkPrimitiveParamsFast(LINK_ROOT, [PRIM_POS_LOCAL, at, PRIM_ROT_LOCAL, FWD]); } ring() { llLinkParticleSystem(LINK_ROOT, [ PSYS_PART_FLAGS, PSYS_PART_EMISSIVE_MASK | PSYS_PART_INTERP_COLOR_MASK | PSYS_PART_INTERP_SCALE_MASK, PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_ANGLE_CONE, PSYS_SRC_ANGLE_BEGIN, PI_BY_TWO, PSYS_SRC_ANGLE_END, PI_BY_TWO, PSYS_SRC_BURST_RADIUS, 0.15, PSYS_SRC_BURST_RATE, 0.09, PSYS_SRC_BURST_PART_COUNT, 140, PSYS_SRC_BURST_SPEED_MIN, 3.2, PSYS_SRC_BURST_SPEED_MAX, 3.6, PSYS_PART_MAX_AGE, 0.5, PSYS_PART_START_SCALE, <0.2, 0.2, 0>, PSYS_PART_END_SCALE, <0.45, 0.45, 0>, PSYS_PART_START_COLOR, <1, 0.97, 0.9>, PSYS_PART_END_COLOR, <0.75, 0.9, 1>, PSYS_PART_START_ALPHA, 0.75, PSYS_PART_END_ALPHA, 0.0, PSYS_PART_START_GLOW, 0.25, PSYS_PART_END_GLOW, 0.0]); } sparks() { llLinkParticleSystem(SPARKS, [ PSYS_PART_FLAGS, PSYS_PART_EMISSIVE_MASK | PSYS_PART_INTERP_COLOR_MASK | PSYS_PART_INTERP_SCALE_MASK | PSYS_PART_FOLLOW_VELOCITY_MASK, PSYS_SRC_PATTERN, PSYS_SRC_PATTERN_EXPLODE, PSYS_SRC_BURST_RADIUS, 0.05, PSYS_SRC_BURST_RATE, 0.06, PSYS_SRC_BURST_PART_COUNT, 45, PSYS_SRC_BURST_SPEED_MIN, 2.0, PSYS_SRC_BURST_SPEED_MAX, 5.5, PSYS_SRC_ACCEL, <0, 0, -5.0>, PSYS_PART_MAX_AGE, 0.9, PSYS_PART_START_SCALE, <0.08, 0.35, 0>, PSYS_PART_END_SCALE, <0.03, 0.12, 0>, PSYS_PART_START_COLOR, <1, 0.95, 0.55>, PSYS_PART_END_COLOR, <1, 0.35, 0.05>, PSYS_PART_START_ALPHA, 1.0, PSYS_PART_END_ALPHA, 0.0, PSYS_PART_START_GLOW, 0.4, PSYS_PART_END_GLOW, 0.05]); } rest() { busy = FALSE; stage = 0; llSetTimerEvent(0); llLinkParticleSystem(LINK_ROOT, []); llLinkParticleSystem(SPARKS, []); place(REST); } go() { if (busy) return; busy = TRUE; stage = 0; t0 = llGetTime(); if (ANIM != "" && (llGetPermissions() & PERMISSION_TRIGGER_ANIMATION)) { llStopAnimation(ANIM); llStartAnimation(ANIM); } llPlaySound(SND_STRETCH, 1.0); llSetTimerEvent(0.04); } setup() { FWD = llEuler2Rot(<0, 90, 0> * DEG_TO_RAD); SPARKS = link_named("sparks"); ANIM = llGetInventoryName(INVENTORY_ANIMATION, 0); llSetLinkPrimitiveParamsFast(LINK_SET, [PRIM_COLOR, ALL_SIDES, <1, 1, 1>, 0.0]); if (llGetAttached()) llRequestPermissions(llGetOwner(), PERMISSION_TRIGGER_ANIMATION); rest(); } default { state_entry() { setup(); llListen(0, "", llGetOwner(), ""); llListen(5, "", llGetOwner(), ""); } on_rez(integer p) { llResetScript(); } attach(key id) { if (id) setup(); } changed(integer c) { if (c & (CHANGED_INVENTORY | CHANGED_LINK)) llResetScript(); } touch_start(integer n) { if (llDetectedKey(0) == llGetOwner()) go(); } listen(integer ch, string name, key id, string msg) { if (ch == 5 || llSubStringIndex(llToLower(msg), "bazooka") != -1) go(); } timer() { float t = llGetTime() - t0; if (stage == 0 && t >= T_WHOOSH) { stage = 1; llPlaySound(SND_FIRE, 1.0); } else if (stage == 1 && t >= T_HIT) { stage = 2; place(HIT); ring(); sparks(); } else if (stage == 2 && t >= T_RING_OFF) { stage = 3; llLinkParticleSystem(LINK_ROOT, []); } else if (stage == 3 && t >= T_HIT + 0.25) { stage = 4; llLinkParticleSystem(SPARKS, []); } else if (stage == 4 && t >= T_END) rest(); } }