aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/locator_beacon_script.lsl
blob: 7af23ed9bc41ebe8152e25636f2bedb9dedea872 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// Onefang's locator beacon script version 1.0.

// A lot of this is just my tweaked up warpPos(), the rest is mostly trivial.  On the other hand, warpPos may be obsolete by now, but it still works.
// The original warpPos() was declared "It's completely public domain." http://forums-archive.secondlife.com/54/8d/109523/1.html
// So I'll put this into the public domain.

integer SIM_CHANNEL = -65767365;
float offset = 128.0;
integer jumpSize = 512;

goThere(vector destPos)
{
    float distance = llVecDist(llGetPos(), destPos);

    if (distance > 0.001)
    {
        integer jumps = 0;
        integer time = llGetUnixTime();
        float oldDistance = 0;
        //llSetPos(destPos);  // This is not any faster, and only has a range of 10 meters.
        //destPos += <0.0, 0.0, 2.0>;  // Try to work around that damned Havok 4 bug.

        // We call the central routine several times to free the massive amount of memory used.
        do
        {
            jumps += warpPos(distance, destPos);
            distance = llVecDist(llGetPos(), destPos);
        }
        while (distance > 1.0 && ((llGetUnixTime() - time) < 2));  // Long jump, no limit.

        // OK, this is just being paranoid, but has been known to be needed in the past.
        while ((distance > 0.001) && (0.001 < (distance - oldDistance))  // Failsafe.
            && ((--jumps) > 0) && ((llGetUnixTime() - time) < 5)) // Time out.
        {
            llOwnerSay("Short hop from " + (string) llGetPos() + " of " + (string) distance + ".  Jumps " + (string) jumps);
            llSetPos(destPos);
            oldDistance = distance;
            distance = llVecDist(llGetPos(), destPos);
            llSleep(0.5);
        }
        if (distance > 0.001)
        {
            llShout(0, "Failed to get to " + (string) destPos + ", I am @ " + (string) llGetPos());
            llInstantMessage(llGetOwner(), "Failed to get to " + (string) destPos + ", I am @ " + (string) llGetPos());
        }
    }
}

integer warpPos(float distance, vector destPos)
{   // R&D by Keknehv Psaltery, 05/25/2006
    // with a little pokeing by Strife, and a bit more
    // some more munging by Talarus Luan
    // Final cleanup by Keknehv Psaltery
    // Extended distance by onefang Rejected.
    // More optimizations by 1fang Fang.

    // Compute the number of jumps necessary.
    integer jumps = (integer) (distance / 10.0) + 1;
    list rules = [PRIM_POSITION, destPos];  // The start for the rules list.
    integer count = 1;

    // Try and avoid stack/heap collisions.
    if (jumps > jumpSize)
    {
        jumps = jumpSize;
        llOwnerSay("Extra warp needed");
    }
    while ((count = count << 1 ) < jumps)
        rules += rules;

    //Changed by Eddy Ofarrel to tighten memory use some more
    llSetPrimitiveParams(rules + llList2List(rules, (count - jumps) << 1, count));
//llOwnerSay("Jumps " + (string) jumps + "   free " + (string) llGetFreeMemory());
    return jumps;
}

init()
{
    vector scale = llGetScale();

    offset = scale.z / 2;
    llListen(SIM_CHANNEL, "", NULL_KEY, "");
}

default
{
    state_entry()
    {
        init();
    }

    on_rez(integer param)
    {
        SIM_CHANNEL = param;
        init();
    }

    attach(key attached)
    {
        init();
    }

    listen(integer channel, string name, key id, string message)
    {
        if ("beacon " == llGetSubString(message, 0, 6))
        {
            vector pos = (vector) llGetSubString(message, 7, -1);

            if (ZERO_VECTOR != pos)
            {
                pos.z += offset;
                // OpenSim bug, first one doesn't quite get there, second one needed.
                // Happens with llSetPos() as well, llSetPrimitiveParams() at least does them both at once.
                // Need warpPos anyway, which hides this bug.
                goThere(pos);
                llSetPrimitiveParams([PRIM_GLOW, ALL_SIDES, 1.0]);
                llSetAlpha(1.0, ALL_SIDES);
            }
        }
        else if ("nobeacon" == message)
            llDie();
    }

    touch_start(integer num_detected)
    {
        vector pos = llGetPos();

        pos.z -= offset;
        llMapDestination(llGetRegionName(), pos, pos);
    }
}