Ice Bullets
LSL Portal | Functions | Events | Types | Operators | Constants | Flow Control | Script Library | Categorized Library | Tutorials |
Created by Kira Komarov based on some tricks on Wizardry and Steamworks.
ChangeLog
- 18 December 2011
Fix for names larger than 24 characters.
Introduction
I have been asked to create a subtle assassination device that would kill an avatar on a SIM with land damage turned on. The purpose was to make the bullets vanish as soon as the task had been accomplished and to make them hard to detect. I know some kids have fun with similar devices on their SIM, so knock yourselves out with it.
Features and Limitations
- The rezzer uses an endless menu to grab the names of the avatars around.
- The ice bullet is transparent and very small sized and hard to select individually.
- You need a clear line of sight, on any collision the bullet will destroy itself.
- If the bullet does not reach its target for any reason, it will destroy itself after a timeout (30 seconds).
- The bullet is homing, it makes course-corrections every 1 seconds.
- When the target is reached, the bullet destroys itself.
Setup
- Create a primitive and set the texture to a transparent texture. Make the prim as small as possible - you may even use a nano sphere. Name the primitive *.
- Copy the Ice Bullet script into the primitive from step 1 named *.
- Take the bullet into your inventory.
- Create a new primitive and place the bullet inside it.
- Copy the script Pea Shooter and place it in the primitive from step 4.
You are set. Click the primitive to select a target. You may also wear the primitive from step 4 as an attachment or add the components to some other attachment.
Code
Ice Bullet - should be placed in a small, transparent textured sphere and the object should be named *.
////////////////////////////////////////////////////////// // [K] Kira Komarov - 2011, License: GPLv3 // // Please see: http://www.gnu.org/licenses/gpl.html // // for legal details, rights of fair usage and // // the disclaimer and warranty conditions. // ////////////////////////////////////////////////////////// //Gremlin: Ice Bullet, see Ice Bullet Peashooter //// integer Key2Number(key objKey) { return ((integer)("0x"+llGetSubString((string)objKey,-8,-1)) & 0x3FFFFFFF) ^ 0xBFFFFFFF; } integer tgtID = 0; key tgtKey = NULL_KEY; integer nTgT = 0; init() { llSetStatus(STATUS_DIE_AT_EDGE | STATUS_PHYSICS, TRUE); llSetDamage(100.0); } integer flag = 0; default { at_target(integer tnum, vector targetpos, vector ourpos) { if(tgtKey == NULL_KEY) return; llSetTimerEvent(0); llDie(); } collision_start(integer num_detected) { llDie(); } timer() { llSetTimerEvent(0); llTargetRemove(nTgT); vector pos = llList2Vector(llGetObjectDetails(tgtKey, [OBJECT_POS]), 0); nTgT = llTarget(pos, 1.0); llMoveToTarget(pos, 0.5); llSetTimerEvent(1); } on_rez(integer param) { tgtID = param; llSensorRepeat("", "", AGENT_BY_LEGACY_NAME, 96, TWO_PI, llGetRegionTimeDilation()); } sensor(integer num_detected) { integer itra; for(itra=0; itra<num_detected; ++itra) { tgtKey = llDetectedKey(itra); if(Key2Number(tgtKey) == tgtID) { llSensorRemove(); vector pos = llList2Vector(llGetObjectDetails(tgtKey, [OBJECT_POS]), 0); nTgT = llTarget(pos, 0.01); init(); llSensorRepeat("", NULL_KEY, flag=1, 0.1, 0.1, 30); llMoveToTarget(pos, 0.045); llSetTimerEvent(1); return; } } } no_sensor() { if(flag--) { return; } llDie(); } }
Pea Shooter - placed in the object rezzing the Ice Bullet.
////////////////////////////////////////////////////////// // [K] Kira Komarov - 2011, License: GPLv3 // // Please see: http://www.gnu.org/licenses/gpl.html // // for legal details, rights of fair usage and // // the disclaimer and warranty conditions. // ////////////////////////////////////////////////////////// //Gremlin: Ice Bullet Peashooter, see Ice Bullet //// integer Key2Number(key objKey) { return ((integer)("0x"+llGetSubString((string)objKey,-8,-1)) & 0x3FFFFFFF) ^ 0xBFFFFFFF; } list mFwd() { if(mitra+1>llGetListLength(menu_items)) return cList; cList = llListInsertList(llListInsertList(llList2List(menu_items, ++mitra, (mitra+=9)), ["<= Back"], 0), ["Next =>"], 2); return cList; } list mBwd() { if(mitra-19<0) return cList; cList = llListInsertList(llListInsertList(llList2List(menu_items, (mitra-=19), (mitra+=9)), ["<= Back"], 0), ["Next =>"], 2); return cList; } list tgtKeys = []; list tgtNames = []; list menu_items = []; integer mitra = 0; list cList = []; integer comHandle = 0; default { touch_start(integer total_number) { if(llDetectedKey(0) != llGetOwner()) return; llSensor("", "", AGENT, 96, TWO_PI); } sensor(integer num_detected) { integer itra; for(itra=0, mitra=0, menu_items=[]; itra<num_detected; ++itra) { tgtKeys += llDetectedKey(itra); tgtNames += llGetSubString(llDetectedName(itra), 0, 23); menu_items += llGetSubString(llDetectedName(itra), 0, 23); } cList = llListInsertList(llListInsertList(llList2List(menu_items, mitra, (mitra+=9)), ["<= Back"], 0), ["Next =>"], 2); integer comChannel = ((integer)("0x"+llGetSubString((string)llGetOwner(),-8,-1)) & 0x3FFFFFFF) ^ 0xBFFFFFFF; comHandle = llListen(comChannel, "", llGetOwner(), ""); llDialog(llGetOwner(), "\nSelect target:\n", menu_items, comChannel); } listen(integer channel, string name, key id, string message) { llListenRemove(comHandle); llRezObject("*", llGetPos() + <0,0,3>, ZERO_VECTOR, ZERO_ROTATION, Key2Number(llList2Key(tgtKeys, llListFindList(tgtNames, (list)llGetSubString(message,0,23))))); } }
Hacks
- One could make the rezzer continuously scan a range for avatars and rez bullets as necessary without intervention - giving you true plow experience.