-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathunsithelper.lsl
118 lines (112 loc) · 5.06 KB
/
unsithelper.lsl
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
//
// Unsit helper - more graceful unsits
//
//
//
// Globals
//
integer gSitting = FALSE; // true if sitting
vector gLastSitPos; // last pos seen sitting
float gAvatarHeight = 2.0; // assumed avatar height, updated later
float gAvatarRadius = 0.5; // assumed avatar radius of enclosing cylinder
list TESTPTS = [<0,1,0>, <1,0,0>, <0,-1,0>, <-1,0,0>]; // test around avatar for open space
//
// teststandpos -- is this a good place to stand?
//
// Returns < 0 if bad, z value of ground if good.
// Input pos is at avatar midpoint Z.
//
float teststandpos(vector pos)
{
vector start = pos + <0,0,gAvatarHeight>; // from well above top of avatar
vector end = pos - <0,0,gAvatarHeight>; // to half its length below ground
list castresult = llCastRay(start, end, []); // vertical cast ray test
integer status = llList2Integer(castresult,-1); // final entry in list is status
if (status < 0) { return(-1.0); } // cast ray problem, fail this point
if (status == 0) { return(0.0); } // no hits, open space.
key hitkey = llList2Key(castresult,0); // what we hit
vector hitpos = llList2Vector(castresult,1); // where we hit
vector disttohit = pos - hitpos;
integer tooclose = disttohit.z < gAvatarHeight/2; // too close
////llOwnerSay("hit " + llKey2Name(hitkey) + " below" + (string)start + " at " + (string)hitpos + " too close: " + (string)tooclose); // ***TEMP***
if (tooclose) // if ground is too close
{ return(-1.0); }
return(hitpos.z); // loc of ground
}
//
// testaroundstandpos - test for enough clearance for an avatar around pos
//
integer testaroundstandpos(vector pos)
{
if (teststandpos(pos) < 0) { return(FALSE); } // obstacle below pos
integer j;
for (j=0; j<llGetListLength(TESTPTS); j++) // test around avatar placement
{ vector testoffsetpos = pos + llList2Vector(TESTPTS,j)*gAvatarRadius;
float z = teststandpos(testoffsetpos); // point near desired avatar placement
if (z < 0) { return(FALSE); } // fails
}
return(TRUE); // success, need to make boolean
}
//
// findstandpos -- find an unobstructed place to stand
//
vector findstandpos(vector pos)
{
integer i;
integer TRIES = 32;
for (i=0; i<TRIES; i++) // spiral outwards from straight ahead
{
float radius = i/8.0; // looking outward
float angle = (i % 8)*PI/4; // angle
vector tryoffset = <llSin(angle),llCos(angle),0>*radius; // offset, starting from straight ahead
vector trypos = pos + tryoffset/llGetRot(); // pos to test
if (tryoffset.x >= 0) // ***TEMP*** don't go behind chair
{ if (testaroundstandpos(trypos)) // success
{ llOwnerSay("Found open space at " + (string) trypos + " offset " + (string)tryoffset + " angle " + (string)(angle*RAD_TO_DEG));
return(trypos);
}
}
}
return(ZERO_VECTOR);
}
//
// stoodup -- avatar just stood up
//
stoodup(vector pos)
{ list bb = llGetBoundingBox(llGetOwner()); // bounding box of avatar
vector mincorner = llList2Vector(bb,0); // corners of bounding box
vector maxcorner = llList2Vector(bb,1);
vector avatardims = maxcorner - mincorner; // dimensions of avatar
llOwnerSay("Avatar dimensions: " + (string)avatardims); // ***TEMP***
gAvatarHeight = avatardims.z;
float avatardiam = avatardims.x;
if (avatardims.y > avatardims.x) { avatardiam = avatardims.y; } // this language needs built-in min
gAvatarRadius = (avatardiam * 0.5)*1.1; // avatar radius, with safety margin
vector target = findstandpos(pos);
if (target == ZERO_VECTOR) { return; }
llMoveToTarget(target, 1.0);
llSleep(1.0);
llStopMoveToTarget();
}
default
{
state_entry()
{
llSetTimerEvent(1.0); // always running timer - bad.
}
timer()
{
{
integer sitting = (llGetAgentInfo(llGetOwner()) & AGENT_SITTING) != 0; // true if sitting now
////llOwnerSay("Sitting: " + (string)sitting);
if (gSitting & !sitting)
{ ////vector pos = llGetPos();
vector pos = gLastSitPos;
llOwnerSay("Stood up at " + (string)pos);
stoodup(pos);
}
if (sitting) { gLastSitPos = llGetPos(); } // record sit position before getting up
gSitting = sitting; // update sitting status
}
}
}