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.