"""Rubber-arm bazooka (a friend's request, inspired by Luffy's Gum Gum Bazooka, 2026-10-11): both arms stretch far back behind the body like rubber, hold, then fire forward palms-out, stretched to about half a body length, and snap back. Uses joint *position* keys on elbows and wrists (SL allows translation anims on all joints). Priority 5, one shot (no loop). Claude Opus 5.5.""" import json from pathlib import Path def arms(back, fwd_reach, stretch_u, stretch_f, palms): """aim directions for both arms plus elbow/wrist offsets (stretch_u: upper arm length, stretch_f: forearm)""" k_aim, k_pos = {}, {} for side, s in (("Left", 1), ("Right", -1)): if back: k_aim[f"mShoulder{side}"] = [-0.9, 0.35 * s, 0.25] k_aim[f"mElbow{side}"] = [-1, 0.15 * s, 0.1] k_aim[f"mWrist{side}"] = [-1, 0.1 * s, 0.1] elif fwd_reach: k_aim[f"mShoulder{side}"] = [1, 0.12 * s, 0.05] k_aim[f"mElbow{side}"] = [1, -0.06 * s, 0.03] k_aim[f"mWrist{side}"] = [0.1, -0.05 * s, 1] if palms else [1, 0, 0] else: k_aim[f"mShoulder{side}"] = [0.3, 0.3 * s, -0.9] k_aim[f"mElbow{side}"] = [0.6, 0.0, 0.8] k_aim[f"mWrist{side}"] = [0.6, 0.0, 0.8] k_pos[f"mElbow{side}"] = [0, round(stretch_u * s, 3), 0] k_pos[f"mWrist{side}"] = [0, round(stretch_f * s, 3), 0] return k_aim, k_pos U, F = 0.248, 0.205 frames = [ # t, back, forward, upper len, fore len, palms, torso pitch (y), pelvis z (0.0, False, False, U, F, False, 0, 0), (0.5, True, False, 0.8, 0.65, False, -18, -0.04), # stretch back (0.9, True, False, 1.2, 1.0, False, -26, -0.06), # way back (a friend's suggestion) (1.9, True, False, 1.25, 1.05, False, -27, -0.06), # held a full second, straining (2.05, False, True, 0.6, 0.5, True, 12, -0.02), # fire! (2.2, False, True, 0.65, 0.55, True, 15, -0.02), # full reach (~1.2 m out) (2.8, False, True, 0.65, 0.55, True, 15, -0.02), # hold (3.1, False, False, U, F, False, 0, 0), # snap back (3.4, False, False, U, F, False, 0, 0), ] keys = [] for t, back, fwd, su, sf, palms, pitch, pz in frames: aim, pos = arms(back, fwd, su, sf, palms) pos["mPelvis"] = [0, 0, pz] keys.append({"t": t, "aim": aim, "pos": pos, "rot": {"mTorso": [0, pitch, 0], "mHead": [0, -pitch * 0.5, 0], "mHipLeft": [0, -10, 0], "mKneeLeft": [0, 18, 0], "mHipRight": [0, 15, 0], "mKneeRight": [0, 10, 0]}}) spec = {"name": "rubber bazooka", "duration": 3.4, "priority": 5, "loop": False, "ease_in": 0.2, "ease_out": 0.3, "hand_pose": "spread", "keys": keys} Path(__file__).with_name("bazooka.json").write_text("// generated by gen_bazooka.py\n" + json.dumps(spec, indent=1))