// IF YOU VALUE THIS WORK, PLEASE LEAVE ATTRIBUTION INTACT // // // // _|_| // // _| _| _|_|_|_| _|_| _|_|_| _|_| // // _| _| _| _| _| _| _| _|_|_|_| // // _| _| _| _| _| _| _| _| // // _|_| _|_|_|_| _|_| _| _| _|_|_| // // MiniVerse // //............................................................// //.....................▒▓▓▒▒▒▒▓▓▓▓▓▓▒▒▒▓▓░....................// //.................._▒▓▒.Ozone.MiniVerse.▒▓▒_.................// //................_▒▓▓▓▒____PRESENTS____▒▓▓▓▓▓▒_..............// //..............░▓▓▓▓▓▓▒___I.M.A.G.E.___▒▓▓▓▓▓▓▓░.............// //.............▒▓▓▓▓▓▓▓▒__IMAGE_MATRIX__▒▓▓▓▓▓▓▓▓▒............// //............▒▓▒▓▓▓▓▒_ACTION_GAME_ENGINE_▒▓▓▓▓▒▓▓▒...........// //..........▒▓▓▓▓░...▒▓▓▒_By_Spax_Orion_▒▓▓▒...░▓▓▓▓▒.........// //.........▒▓▓▓▓░......▒▓_& Dirty Helga_▓▓▒░.....░▒▓▓▓........// //.........▓▓▓▓▒░.._......░▒▓▓▓▓▓▓▓▓▓▓▓▒░......_..░▒▓▓▓.......// //.........▓▓▓▓░.._▓░▓░_....▓▓▓▓▓▓▓▓▓▓...._▒▓▒▓_..░▓▓▓▓.......// //.........▓▓▓▓.._▓█░▒█▒.....▒▓▓▓▓▓▓▒.....▒█▒░█▒_..▓▓▓▓.......// //........▒▓▓▓▓▓▒_..▒._░_▒▓▓▒░.▒▒.░▒▓▓▒_░_.▒.._▒▓▓▓▓▓▓▒.......// //.......▒▓▓▓▓▓▓▓▓▓_...▒▓▓▓▓▓░..▒▒..░▓▓▓▓▓▒..._▓▓▓▓▓▓▓▓▒......// //......▓▓▓▓▓▓▓▓▓▓▓_.▓▓▓▓▓▒.._▓▓▓█_..▒▓▓▓▓▓._▓▓▓▓▓▓▓▓▓▓▓......// //......▓▓▓▓▓▒▒▓▓▓▒▓▓▓▓▓▓▒░.▒▓▓▓▓▓█▒.░▒▓▓▓▓▓▒▒▓▓▓▒▓▓▓▓▓▓......// //......▓▓▓▓▓░.▓▓▓.▒▓▓▓▓▓░..▒▓▓▓▓▓▓▒..░▓▓▓▓▓░.▓▓▓.░▓▓▓▓▓......// //........▒▓▓█░.▓▓▓.▒▓▓▓▓▓__▓_..▒▒.._▓__▓▓▓▓▓░.▓▓▓.▒▓▓▓▒......// //.........░▒░░▒▓▒░▒▓▓▓▓▓▓▒▒▓▒▒▒▓▓▒▒▒▓▒▒▓▓▓▓▓▒░▒▓▒░░▒░░.......// //.........░▒.░▓▓░.▓▓▓▓█▒▒▒█▒▒▒█▒▒█▒▒▒█▒▒▒█▓▓▓▓.░▓▓░.▒░.......// //.............░▓▓░_▓▓▓▓█................█▓▓▓▓_░▓▓░...........// //..............░▒▓▓▓█▓._▒_.█░....█░._█_.▓█▓▓▓▒░..............// //.................░▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓░................// //.................░▒▓▓▓▒▒▓▒▒▓▓▓▓▒▒▓▓▓▓▒▒▓▓▒░.................// //..................▒▓▓░░▓░░▓▓▓▓░░▓▓▓▓░░▓▓▒...................// //.................▒▓░..█__▓▓▓▓__▓▓▓▓__█..░▓▒.................// //...................░...░..░▓▓░..░▓▓░..░...░.................// //.................... ..░...░▒░....░▒░...░...................// //............................................................// // Common sense not included and must be supplied by end user // // Read ENTIRE script first and LEARN: KNOW what you're using // // CC BY-NC https://creativecommons.org/licenses/by-nc/4.0/ // // ===========================================================// // IMAGE INCOGNITO // // Mouselook firing, attachment point irrelevant, // // llCastRay + osCauseDamage, with a visible slug tracer. // // ===========================================================// // part of slugshooter prim // Inventory name of the bullet object inside the gun string AMMO_OBJECT = "slug"; // Fire sound in gun inventory string FIRE_SOUND = "zap"; float FIRE_VOLUME = 1.0; // ------------------------------------------------------------ // FEEL / BALANCE TUNING float BULLET_VELOCITY = 60.0; float REPEAT_DELAY = 0.35; integer DAMAGE_DICE = 5; // ------------------------------------------------------------ // HITSCAN (RAY) TUNING float RAY_START_FWD = 1.0; float RAY_RANGE = 80.0; integer USE_CONE = TRUE; float CONE_SPREAD = 0.012; // ------------------------------------------------------------ // VISUAL TRACER OFFSET vector MUZZLE_OFFSET = <1.10, -0.25, 0.75>; // ------------------------------------------------------------ integer gFiringLock = FALSE; // One ray cast with a small lateral/up offset (for cone shots) key castOneRay(vector cpos, rotation crot, vector lateral) { vector fwd = llRot2Fwd(crot); vector left = llRot2Left(crot); vector up = llRot2Up(crot); vector dir = llVecNorm(fwd + (left * lateral.x) + (up * lateral.y)); vector start = cpos + (fwd * RAY_START_FWD); vector end = start + (dir * RAY_RANGE); list results = llCastRay( start, end, [ RC_DETECT_PHANTOM, FALSE, RC_DATA_FLAGS, RC_GET_ROOT_KEY, RC_MAX_HITS, 1 ] ); return llList2Key(results, 0); } // Cone logic: try center, then a left ray, then a right ray. key doRaycastHit() { vector cpos = llGetCameraPos(); rotation crot = llGetCameraRot(); if (!USE_CONE) return castOneRay(cpos, crot, <0.0, 0.0, 0.0>); key k; k = castOneRay(cpos, crot, <0.0, 0.0, 0.0>); if (k) return k; k = castOneRay(cpos, crot, ); if (k) return k; k = castOneRay(cpos, crot, <-CONE_SPREAD, 0.0, 0.0>); if (k) return k; return NULL_KEY; } fire() { if (gFiringLock) return; gFiringLock = TRUE; // Fire sound (requested) if (llGetInventoryType(FIRE_SOUND) == INVENTORY_SOUND) llPlaySound(FIRE_SOUND, FIRE_VOLUME); // Use camera rotation so attachment point does not matter. rotation rot = llGetCameraRot(); // Visible tracer slug (visual only) vector pos = llGetPos(); pos += (MUZZLE_OFFSET * rot); vector vel = llRot2Fwd(rot) * BULLET_VELOCITY; rotation rezRot = rot * llEuler2Rot(<0, PI_BY_TWO, 0>); llRezObject(AMMO_OBJECT, pos, vel, rezRot, DAMAGE_DICE); // Hitscan damage key target = doRaycastHit(); if (target != NULL_KEY) { osCauseDamage(target, DAMAGE_DICE); } llSetTimerEvent(REPEAT_DELAY); } default { state_entry() { llRequestPermissions(llGetOwner(), PERMISSION_TAKE_CONTROLS | PERMISSION_TRACK_CAMERA); llSetTimerEvent(0.0); } on_rez(integer p) { llResetScript(); } attach(key id) { if (id) llResetScript(); } run_time_permissions(integer perm) { if (perm & PERMISSION_TAKE_CONTROLS) { llTakeControls(CONTROL_ML_LBUTTON, TRUE, FALSE); } } control(key id, integer level, integer edge) { id = NULL_KEY; // lint integer pressed = level & edge; if (pressed & CONTROL_ML_LBUTTON) { fire(); } } timer() { llSetTimerEvent(0.0); gFiringLock = FALSE; } } /* // ============================================================ // GRUG ASSAULT - Slug Shooter (LiteCast / bloat-minimized) // Fires in mouselook toward camera direction (attachment point irrelevant). // Reliable hits via llCastRay + osCauseDamage, with a visible slug tracer. // // TUNING PHILOSOPHY: // - Hit reliability is controlled by RAY_RANGE and (optionally) the cone rays. // - "Bullet feel" is controlled by BULLET_VELOCITY and REPEAT_DELAY. // - Region lag is dominated by rez rate (REPEAT_DELAY) and particle spam, // not by the raycast itself. // ============================================================ // Inventory name of the bullet object inside the gun string AMMO_OBJECT = "slug"; // ------------------------------------------------------------ // FEEL / BALANCE TUNING // How fast the tracer slug travels. // NOTE: Hit detection is hitscan (ray) so speed mainly affects visuals/feel. float BULLET_VELOCITY = 60.0; // raise for snappier feel; 45-80 typical // Rate of fire. // NOTE: Lower than ~0.25 can become spammy (rezzing bullets costs sim time). float REPEAT_DELAY = 0.35; // 0.30-0.50 usually safe and fun // Damage applied by osCauseDamage when a ray hit is found. // You can raise this if Grugs feel too tanky, or lower if too easy. integer DAMAGE_DICE = 5; // try 4 if you want faster kills // ------------------------------------------------------------ // HITSCAN (RAY) TUNING // Avoid self-hits / odd camera-in-body issues: start the ray slightly forward. float RAY_START_FWD = 1.0; // 0.5..1.5; raise if you ever "hit yourself" // Max range of the hitscan. // If your Grugs are far away or you want long shots, increase this. float RAY_RANGE = 80.0; // 60..120 typical // If TRUE, we fire 3 rays (center, left, right) to create a forgiving cone. // This helps with "hard to hit" targets without increasing damage. // If FALSE, we fire only 1 ray (least overhead). integer USE_CONE = TRUE; // Cone spread for the side rays. // Smaller = tighter aim required; larger = more forgiving. // 0.008 subtle, 0.012 moderate, 0.020 generous. float CONE_SPREAD = 0.012; // ------------------------------------------------------------ // VISUAL TRACER OFFSET (where the slug rezzes relative to camera) // This is in camera-local space: // If your slug appears too high/low/left/right, tweak these. // Forward controls how far in front of you the slug appears. vector MUZZLE_OFFSET = <1.10, -0.25, 0.75>; // ------------------------------------------------------------ integer gFiringLock = FALSE; // One ray cast with a small lateral/up offset (for cone shots) key castOneRay(vector cpos, rotation crot, vector lateral) { vector fwd = llRot2Fwd(crot); vector left = llRot2Left(crot); vector up = llRot2Up(crot); // "dir" is a slightly offset forward vector for the cone. vector dir = llVecNorm(fwd + (left * lateral.x) + (up * lateral.y)); vector start = cpos + (fwd * RAY_START_FWD); vector end = start + (dir * RAY_RANGE); list results = llCastRay( start, end, [ // We do NOT detect phantom targets by default. // If your NPC/object is phantom and you want to hit it, set TRUE. RC_DETECT_PHANTOM, FALSE, // Ask for root key; reduces "hit a child prim" ambiguity. RC_DATA_FLAGS, RC_GET_ROOT_KEY, // We only care about the nearest hit. RC_MAX_HITS, 1 ] ); return llList2Key(results, 0); } // Cone logic: try center, then a left ray, then a right ray. key doRaycastHit() { vector cpos = llGetCameraPos(); rotation crot = llGetCameraRot(); if (!USE_CONE) return castOneRay(cpos, crot, <0.0, 0.0, 0.0>); key k; k = castOneRay(cpos, crot, <0.0, 0.0, 0.0>); if (k) return k; k = castOneRay(cpos, crot, ); if (k) return k; k = castOneRay(cpos, crot, <-CONE_SPREAD, 0.0, 0.0>); if (k) return k; return NULL_KEY; } fire() { if (gFiringLock) return; gFiringLock = TRUE; // Use camera rotation so attachment point does not matter. rotation rot = llGetCameraRot(); // Rez a visible tracer slug for feedback (big + red glow as you like). // This does not drive hit detection, it is purely visual. vector pos = llGetPos(); pos += (MUZZLE_OFFSET * rot); vector vel = llRot2Fwd(rot) * BULLET_VELOCITY; // Some older content expects bullets to be rotated 90 degrees; keep it. rotation rezRot = rot * llEuler2Rot(<0, PI_BY_TWO, 0>); // Pass DAMAGE_DICE as rez param in case you ever want the slug to use it. llRezObject(AMMO_OBJECT, pos, vel, rezRot, DAMAGE_DICE); // Hitscan: apply damage immediately to whatever the ray finds. key target = doRaycastHit(); if (target != NULL_KEY) { osCauseDamage(target, DAMAGE_DICE); // If you want debugging, uncomment: // llOwnerSay("Hit " + llKey2Name(target)); } llSetTimerEvent(REPEAT_DELAY); } default { state_entry() { // Minimal permissions: we only need controls + camera tracking. llRequestPermissions(llGetOwner(), PERMISSION_TAKE_CONTROLS | PERMISSION_TRACK_CAMERA); llSetTimerEvent(0.0); } on_rez(integer p) { llResetScript(); } attach(key id) { if (id) llResetScript(); } run_time_permissions(integer perm) { if (perm & PERMISSION_TAKE_CONTROLS) { // Fires on left mouse button while in mouselook. llTakeControls(CONTROL_ML_LBUTTON, TRUE, FALSE); } } control(key id, integer level, integer edge) { id = NULL_KEY; // lint integer pressed = level & edge; if (pressed & CONTROL_ML_LBUTTON) { fire(); } } timer() { llSetTimerEvent(0.0); gFiringLock = FALSE; } }