diff options
author | Dave Seikel | 2018-05-20 23:17:24 +1000 |
---|---|---|
committer | Dave Seikel | 2018-05-20 23:17:24 +1000 |
commit | 9dd74045373c39d8a35a59f3c2801b0348a44a9b (patch) | |
tree | b3cdc4ba800ffa44b98291ce12a0eb1c9ad809e4 /~MLP lite props.lsl | |
parent | Initial commit (diff) | |
download | MLP-lite-9dd74045373c39d8a35a59f3c2801b0348a44a9b.zip MLP-lite-9dd74045373c39d8a35a59f3c2801b0348a44a9b.tar.gz MLP-lite-9dd74045373c39d8a35a59f3c2801b0348a44a9b.tar.bz2 MLP-lite-9dd74045373c39d8a35a59f3c2801b0348a44a9b.tar.xz |
Initial commit.
This is the current alpha version, it was time to put it somewhere.
Diffstat (limited to '~MLP lite props.lsl')
-rw-r--r-- | ~MLP lite props.lsl | 354 |
1 files changed, 354 insertions, 0 deletions
diff --git a/~MLP lite props.lsl b/~MLP lite props.lsl new file mode 100644 index 0000000..f8042e4 --- /dev/null +++ b/~MLP lite props.lsl | |||
@@ -0,0 +1,354 @@ | |||
1 | // | ||
2 | // MLP lite v3.0 for OpenSim | ||
3 | // Based on the original MLP - MULTI-LOVE-POSE V1.2 - Copyright (c) 2006, by Miffy Fluffy (BSD License) | ||
4 | // This code has bounced around the Second Life and OpenSim for over a decade, with various people working on it. | ||
5 | // MLP lite for OpenSim is almost a complete rewrite by onefang rejected. | ||
6 | |||
7 | vector RefPos; | ||
8 | rotation RefRot; | ||
9 | |||
10 | string Pose = ""; | ||
11 | |||
12 | list Props; // List of props. | ||
13 | integer PROP_NAME = 0; // Name of prop, which should match a POSE name. | ||
14 | integer PROP_OBJECT = 1; // | separated names of props in inventory. | ||
15 | integer PROP_POSROT = 2; // | separated position and rotation pairs. | ||
16 | integer PROP_STRIDE = 3; | ||
17 | |||
18 | list Balls; // Ball / prop tracker. | ||
19 | integer BALL_NUM = 0; // The number of the ball, negative numbers for the props. | ||
20 | integer BALL_KEY = 1; // The UUID of the ball / prop. | ||
21 | integer BALL_AVATAR = 2; // The UUID of any avatar sitting on the ball. | ||
22 | integer BALL_STRIDE = 3; | ||
23 | |||
24 | string LIST_SEP = "$!#"; // Used to seperate lists when sending them as strings. | ||
25 | |||
26 | // The various link messages. The first lot are historical. | ||
27 | //integer OLD_TOUCH = -1; // msg = "PRIMTOUCH" | ||
28 | integer OLD_POSEB = 0; // msg = "POSEB" id = pose name | ||
29 | // // Also CHECK1 and CHECK2 instead of pose name. | ||
30 | integer OLD_STOP = 1; // msg = "STOP" | ||
31 | //integer OLD_REF = 8; // msg = RefPos id = RefRot | ||
32 | integer OLD_SITS = -11000; // msg = ball number|anim name id = avatar key | ||
33 | integer OLD_STANDS = -11001; // msg = ball number id = avatar key | ||
34 | integer OLD_ANIM = -11002; // msg = ball number|anim name id = avatar key | ||
35 | //integer SEQ_CMD = -12001; // msg = ~sequencer command | ||
36 | integer OLD_CMD = -12002; // msg = menu command for ~MLP id = user key | ||
37 | |||
38 | integer MLP_CMD = -13001; // A command that ~MLP dealt with, so other scripts can hook it. | ||
39 | integer TOOL_DATA = -13002; // Get Menus, Poses, Props, or Sounds list. | ||
40 | integer MLP_DATA = -13003; // Set Menus, Poses, Props, or Sounds list. | ||
41 | integer MLP_POSE = -13004; // doPose(pose, type); | ||
42 | integer MLP_UNKNOWN = -13005; // ~MLP doesn't know this command, might be for other scripts. | ||
43 | |||
44 | // Types for doPose(), | ||
45 | integer POSES_POSE = -14001; // Change pose, even if it's changing to the same pose. | ||
46 | integer POSES_SWAP = -14002; // Swap poses. | ||
47 | integer POSES_DUMP = -14003; // Dump or save poses. | ||
48 | integer POSES_Z = -14004; // Change height. | ||
49 | |||
50 | |||
51 | integer listFindString(list lst, string name, integer stride) | ||
52 | { | ||
53 | integer f = llListFindList(lst, [name]); | ||
54 | integer ix = f / stride; | ||
55 | |||
56 | // Round to nearest stride. | ||
57 | ix = ix * stride; | ||
58 | |||
59 | // Sanity check, make sure we found a name, not something else, else do it the slow way. | ||
60 | if ((-1 != f) && (ix != f)) | ||
61 | { | ||
62 | integer l = llGetListLength(lst); | ||
63 | integer i; | ||
64 | |||
65 | f = -1; | ||
66 | for (i = 0; i < l; i += stride) | ||
67 | { | ||
68 | if (llList2String(lst, i) == name) | ||
69 | { | ||
70 | f = i; | ||
71 | i = l; | ||
72 | } | ||
73 | } | ||
74 | } | ||
75 | return f; | ||
76 | } | ||
77 | |||
78 | // Only used in one place, but leave it here for now. | ||
79 | string prStr(string str) | ||
80 | { | ||
81 | integer ix = llSubStringIndex(str, ">"); | ||
82 | vector p = ((vector) llGetSubString(str, 0, ix) - RefPos) / RefRot; | ||
83 | vector r = llRot2Euler((rotation) llGetSubString(str, ix + 1, -1) / RefRot) * RAD_TO_DEG; | ||
84 | |||
85 | // OpenSim likes to swap these around, which triggers the ball movement saving. | ||
86 | // Coz OpenSim doesn't support move events, so we gotta do things the hard way. | ||
87 | if (-179.9 >= r.x) r.x = 180.0; | ||
88 | if (-179.9 >= r.y) r.y = 180.0; | ||
89 | if (-179.9 >= r.z) r.z = 180.0; | ||
90 | |||
91 | return "<" + round(p.x, 3) + "," + round(p.y, 3) + "," + round(p.z, 3) + | ||
92 | "><" + round(r.x, 1) + "," + round(r.y, 1) + "," + round(r.z, 1) + ">"; | ||
93 | } | ||
94 | |||
95 | string round(float number, integer places) | ||
96 | { | ||
97 | float shifted; | ||
98 | integer rounded; | ||
99 | string s; | ||
100 | |||
101 | shifted = number * llPow(10.0, (float) places); | ||
102 | rounded = llRound(shifted); | ||
103 | s = (string) ((float) rounded / llPow(10.0, (float)places)); | ||
104 | rounded = llSubStringIndex(s, "."); | ||
105 | if (-1 != rounded) | ||
106 | s = llGetSubString(s, 0, llSubStringIndex(s, ".") + places); | ||
107 | else | ||
108 | { | ||
109 | s += ".00000000"; | ||
110 | s = llGetSubString(s,0,llSubStringIndex(s, ".") + places); | ||
111 | } | ||
112 | return s; | ||
113 | } | ||
114 | |||
115 | integer findBall(integer num) | ||
116 | { | ||
117 | integer f = llListFindList(Balls, [num]); | ||
118 | integer ix = f / BALL_STRIDE; | ||
119 | |||
120 | // Round to nearest stride. | ||
121 | ix = ix * BALL_STRIDE; | ||
122 | |||
123 | if ((-1 != f) && (ix == f)) // Sanity check, make sure we found a chan, not something else. | ||
124 | return f; | ||
125 | else | ||
126 | return -1; | ||
127 | } | ||
128 | |||
129 | saveBall(integer num, key id, key avatar) | ||
130 | { | ||
131 | integer f = findBall(num); | ||
132 | |||
133 | if (-1 == f) | ||
134 | Balls += [num, id, avatar]; | ||
135 | else | ||
136 | Balls = llListReplaceList(Balls, [num, id, avatar], f, f + BALL_STRIDE - 1); | ||
137 | } | ||
138 | |||
139 | rezThing(string thing, string posRot, integer num) | ||
140 | { | ||
141 | integer i = llSubStringIndex(posRot, ">"); | ||
142 | |||
143 | llRezObject(thing, | ||
144 | ((vector) llGetSubString(posRot, 0, i)) * RefRot + RefPos, | ||
145 | ZERO_VECTOR, | ||
146 | llEuler2Rot((vector) llGetSubString(posRot, i + 1, -1) * DEG_TO_RAD) * RefRot, | ||
147 | num); | ||
148 | } | ||
149 | |||
150 | readProps(list propCards) | ||
151 | { | ||
152 | integer i; | ||
153 | integer l = llGetListLength(propCards); | ||
154 | |||
155 | propCards = llListSort(propCards, 1, TRUE); | ||
156 | for (i = 0; i < l; i++) | ||
157 | { | ||
158 | string card = llList2String(propCards, i); | ||
159 | list crd = llParseStringKeepNulls(osGetNotecard(card), ["\n"], []); | ||
160 | integer m = llGetListLength(crd); | ||
161 | integer j; | ||
162 | |||
163 | llOwnerSay("Reading '" + card + "'."); | ||
164 | for (j = 0; j < m; j++) | ||
165 | { | ||
166 | string data = llList2String(crd, j); | ||
167 | |||
168 | if (llGetSubString(data, 0, 0) != "/") | ||
169 | { // skip comments | ||
170 | data = llStringTrim(data, STRING_TRIM); | ||
171 | if ("" != data) | ||
172 | { | ||
173 | // .PROPS is different from .POSITIONS, which is just inconsistant. | ||
174 | // There's an extra | at the beginning of the lines, for no apparent reason. | ||
175 | // The position and rotation has a "/" between them, and normally / is a comment. | ||
176 | // But we gotta stay compatible. sigh | ||
177 | list props = llParseStringKeepNulls(data, ["|"], []); | ||
178 | string name = llStringTrim(llList2String(props, 1), STRING_TRIM); | ||
179 | string prop = llStringTrim(llList2String(props, 2), STRING_TRIM); | ||
180 | list posrots = llParseString2List(llStringTrim(llList2String(props, 3), STRING_TRIM), ["/"], []); | ||
181 | |||
182 | saveProp(name, prop, llDumpList2String(posrots, "")); | ||
183 | } | ||
184 | } | ||
185 | } | ||
186 | } | ||
187 | } | ||
188 | |||
189 | integer findProp(string name) | ||
190 | { | ||
191 | return listFindString(Props, name, PROP_STRIDE); | ||
192 | } | ||
193 | |||
194 | saveProp(string name, string prop, string posRot) | ||
195 | { | ||
196 | integer f = findProp(name); | ||
197 | |||
198 | if (-1 != f) | ||
199 | { | ||
200 | string t; | ||
201 | |||
202 | t = llList2String(Props, f + PROP_OBJECT); | ||
203 | if ("" != t) | ||
204 | prop += "|" + prop; | ||
205 | t = llList2String(Props, f + PROP_POSROT); | ||
206 | if ("" != t) | ||
207 | posRot += "|" + posRot; | ||
208 | Props = llListReplaceList(Props, [name, prop, posRot], f, f + PROP_STRIDE - 1); | ||
209 | } | ||
210 | else | ||
211 | Props += [name, prop, posRot]; | ||
212 | } | ||
213 | |||
214 | // ball is either the ball number, or a POSES_* flag. | ||
215 | // ball on the other hand, is a negative integer for props. | ||
216 | doPose(string newPose, integer ball) | ||
217 | { | ||
218 | integer f = findProp(Pose); | ||
219 | integer p = findBall(ball); | ||
220 | integer l = llGetListLength(Balls); | ||
221 | integer i = 0; | ||
222 | vector newRefPos = llGetPos(); | ||
223 | rotation newRefRot = llGetRot(); | ||
224 | |||
225 | newRefPos.z += ((integer) llGetObjectDesc()) / 100.0; | ||
226 | |||
227 | if (-1 != p) | ||
228 | { | ||
229 | i = p; | ||
230 | l = p + BALL_STRIDE; | ||
231 | } | ||
232 | for (; i < l; i += BALL_STRIDE) | ||
233 | { | ||
234 | integer b0 = llList2Integer(Balls, i + BALL_NUM); | ||
235 | integer isBall = (0 <= b0); | ||
236 | |||
237 | if (isBall) | ||
238 | ; | ||
239 | else //if ((POSES_SWAP != ball) | ||
240 | { | ||
241 | if (-1 != f) | ||
242 | { | ||
243 | integer m = f + PROP_POSROT; | ||
244 | string prOld = llList2String(Props, m); | ||
245 | // Find out where the prop is now, and rotation. | ||
246 | integer q = -1 - b0; | ||
247 | string bpr = prStr(llDumpList2String( | ||
248 | llGetObjectDetails(llList2Key(Balls, i + BALL_KEY), [OBJECT_POS, OBJECT_ROT]), "")); | ||
249 | string result = llDumpList2String(llListReplaceList(llParseString2List(prOld, ["|"], []), [bpr], q, q), "|"); | ||
250 | // Actually store the props new position / rotation if it moved. | ||
251 | if (result != prOld) | ||
252 | { | ||
253 | llOwnerSay(" MOVEd prop " + q + ".\n\t old [" + prOld + "]\n\t new [" + result + "]"); | ||
254 | Props = llListReplaceList(Props, [result], m, m); | ||
255 | } | ||
256 | } | ||
257 | |||
258 | if ((POSES_DUMP != ball) && (POSES_SWAP != ball)) | ||
259 | { | ||
260 | // Remove the prop. | ||
261 | osMessageObject(llList2Key(Balls, i + BALL_KEY), "DIE"); | ||
262 | Balls = llListReplaceList(Balls, [], i, i + BALL_STRIDE - 1); | ||
263 | i -= BALL_STRIDE; | ||
264 | l -= BALL_STRIDE; | ||
265 | } | ||
266 | } | ||
267 | } | ||
268 | RefPos = newRefPos; | ||
269 | RefRot = newRefRot; | ||
270 | |||
271 | // Props are per pose, so deal with them here to. | ||
272 | // Assumption - props don't MOVE when we change poses, they die, and get recreated when needed. | ||
273 | // Note that the original MLP also assumed that props don't MOVE, though they send MOVE. | ||
274 | if (POSES_POSE == ball) | ||
275 | { | ||
276 | p = findProp(newPose); | ||
277 | if (-1 != p) | ||
278 | { | ||
279 | list o = llParseStringKeepNulls(llList2String(Props, p + PROP_OBJECT), ["|"], []); | ||
280 | list q = llParseStringKeepNulls(llList2String(Props, p + PROP_POSROT), ["|"], []); | ||
281 | |||
282 | l = llGetListLength(o); | ||
283 | for (i = 0; i < l; i++) | ||
284 | rezThing(llList2String(o, i), llList2String(q, i), -1 - i); | ||
285 | } | ||
286 | } | ||
287 | Pose = newPose; | ||
288 | } | ||
289 | |||
290 | |||
291 | default | ||
292 | { | ||
293 | link_message(integer from, integer num, string str, key id) | ||
294 | { | ||
295 | if (((0 == num) && ("POSEB" == str)) || ((1 == num) && ("STOP" == str))) | ||
296 | ; // Old messages we can ignore. | ||
297 | else if ((MLP_UNKNOWN == num) && ("LOADPROPS" == str)) | ||
298 | { | ||
299 | float then = llGetTime(); | ||
300 | float now = 0.0; | ||
301 | list propCards = []; // List of names of config cards. | ||
302 | string item; | ||
303 | integer i = llGetInventoryNumber(INVENTORY_NOTECARD); | ||
304 | integer PropCount; | ||
305 | |||
306 | while (i-- > 0) | ||
307 | { | ||
308 | item = llGetInventoryName(INVENTORY_NOTECARD, i); | ||
309 | if (llSubStringIndex(item, ".PROPS") == 0) | ||
310 | propCards += (list) item; | ||
311 | } | ||
312 | Props = []; | ||
313 | readProps(propCards); | ||
314 | PropCount = llGetListLength(Props) / PROP_STRIDE; | ||
315 | if (0 < PropCount) | ||
316 | { | ||
317 | now = llGetTime(); | ||
318 | llOwnerSay("Loaded " + PropCount + " props in " + (string) (now - then) + " seconds."); | ||
319 | } | ||
320 | } | ||
321 | else if (MLP_POSE == num) | ||
322 | { | ||
323 | if (NULL_KEY == id) | ||
324 | id = Pose; | ||
325 | doPose((string) id, (integer) str); | ||
326 | } | ||
327 | else if (TOOL_DATA == num) | ||
328 | { | ||
329 | if ("" == str) | ||
330 | { | ||
331 | if ("Props" == id) | ||
332 | llMessageLinked(from, num, LIST_SEP + llDumpList2String(Props, LIST_SEP), id); | ||
333 | } | ||
334 | else | ||
335 | { | ||
336 | if ("Props" == id) | ||
337 | Props = llParseStringKeepNulls(llGetSubString(str, llStringLength(LIST_SEP), -1), [LIST_SEP], []); | ||
338 | } | ||
339 | } | ||
340 | else if ((OLD_CMD == num) || (MLP_CMD == num) || (MLP_UNKNOWN == num) | ||
341 | || (OLD_SITS == num) || (OLD_STANDS == num) || (OLD_ANIM == num)) | ||
342 | ; | ||
343 | else | ||
344 | llOwnerSay(llGetScriptName() + " Unknown link message " + num + ", " + str); | ||
345 | } | ||
346 | |||
347 | dataserver(key queryId, string str) | ||
348 | { | ||
349 | list data = llParseString2List(str, ["|"], []); | ||
350 | |||
351 | if ("ALIVE" == llList2String(data, 0)) | ||
352 | saveBall(llList2Integer(data, 1), queryId, NULL_KEY); | ||
353 | } | ||
354 | } | ||