diff options
author | David Walter Seikel | 2014-04-22 14:22:30 +1000 |
---|---|---|
committer | David Walter Seikel | 2014-04-22 14:22:30 +1000 |
commit | 1d0bfbe0388309d17839d091e6069b0942b07efb (patch) | |
tree | 7ae33a3fcc45d00eff7920298d01ed5b5e3b0ac7 /media/Test sim | |
parent | And update .gitignore to match. (diff) | |
download | SledjHamr-1d0bfbe0388309d17839d091e6069b0942b07efb.zip SledjHamr-1d0bfbe0388309d17839d091e6069b0942b07efb.tar.gz SledjHamr-1d0bfbe0388309d17839d091e6069b0942b07efb.tar.bz2 SledjHamr-1d0bfbe0388309d17839d091e6069b0942b07efb.tar.xz |
Move the test sim to the media directory.
Diffstat (limited to 'media/Test sim')
23 files changed, 4093 insertions, 0 deletions
diff --git a/media/Test sim/index.omg b/media/Test sim/index.omg new file mode 100644 index 0000000..afb422a --- /dev/null +++ b/media/Test sim/index.omg | |||
@@ -0,0 +1,2 @@ | |||
1 | <125.432899,128.229706,3500.5> <0.5,5.,5.> <0.,270.,180.> objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/index.omg | ||
2 | |||
diff --git a/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/.MENUITEMS b/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/.MENUITEMS new file mode 100644 index 0000000..3ea96ee --- /dev/null +++ b/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/.MENUITEMS | |||
@@ -0,0 +1,211 @@ | |||
1 | POSE stand | stand | stand | stand //pose before starting and when stopping | ||
2 | POSE default | sit_ground | sit_ground | sit_ground //default pose when no animation entered | ||
3 | |||
4 | MENUORDER // use new (sane) menu button order -- same as in files. Omit this for MLP compatibility. | ||
5 | // NORELOAD // inhibit reload on rez -- use for worn item, but "Menu Reset" if you make a copy! | ||
6 | |||
7 | |||
8 | MENU MAIN MENU | ALL | ||
9 | TOMENU Relax | ||
10 | TOMENU Hugs | ||
11 | TOMENU Dances | ||
12 | TOMENU Lick girl | ||
13 | TOMENU Lick boy | ||
14 | TOMENU Stand sex | ||
15 | TOMENU Girl on top | ||
16 | TOMENU Boy on top | ||
17 | TOMENU Side by side | ||
18 | TOMENU - // 10 (total) blank spaces for modular configs. Unused entries are automatically deleted. | ||
19 | STOP //remove poseballs | ||
20 | TOMENU Options >> // options menu | ||
21 | |||
22 | |||
23 | MENU Dances | ALL | BLUE | PINK | ||
24 | TOMENU Slow dances | ||
25 | BACK | ||
26 | |||
27 | |||
28 | MENU Slow dances | ALL | BLUE | PINK | ||
29 | SWAP | ||
30 | BACK | ||
31 | |||
32 | |||
33 | MENU Relax | ALL | BLUE | PINK | ||
34 | POSE pillow-sit | sit_ground | sit_ground | ||
35 | //POSE sit 1 | sitting chair f07 | sitting ground f08 | ||
36 | //POSE sit 2 | sitting ground f02 | sitting ground f03 | ||
37 | POSE sit2 | sit_ground | sit_ground | ||
38 | //POSE sit 3 | lovermale14 | lovefemale14 | ||
39 | //POSE sit 4 | lovefemale20b|flay6 | ||
40 | //POSE sit 5 | f_yabyum3 | sitting ground f05 | ||
41 | //POSE sit 6 | sitting ground f01 | sitting ground f04 | ||
42 | //POSE sit 7 | sitting couch f07 | sitting couch f06 | ||
43 | POSE standing | stand | stand | ||
44 | //SOUND ☊guitar | mood4aday | ||
45 | TOMENU Meditation | ||
46 | TOMENU 6-way | ||
47 | SWAP | ||
48 | BACK | ||
49 | |||
50 | |||
51 | MENU Meditation | ALL | BLUE | PINK | ||
52 | //POSE Birth | m2_birth | f2_birth | ||
53 | //POSE Birth 1 | m2_birth | f2_birth | ||
54 | //POSE Pray| praykneeing2 | praykneeing2 1 | ||
55 | //POSE Meditate | med f4 | med f4 1 | ||
56 | //POSE Meditate 1 | m_meditation | f_meditation | ||
57 | //POSE YabYum | R lovemale19d | R lovefemale19a | ||
58 | SWAP | ||
59 | BACK | ||
60 | |||
61 | |||
62 | MENU 6-way | ALL | BLUE | PINK | GREEN | RED | BLUE2 | PINK2 | ||
63 | POSE default | sit_ground | sit_ground | sit_ground | sit_ground | ||
64 | POSE 6way-1 | jP-sit-m-01-filt | jP-sit-f-03-filt | jP-sit-m-02-filt | jP-sit-f-04-filt | jP-sit-m-03-filt | jP-sit-f-05-filt | ||
65 | POSE 6way-2 | jP-sit-m-03-filt | jP-sit-f-05-filt | jP-sit-m-02-filt | jP-sit-f-04-filt | jP-sit-m-01-filt | jP-sit-f-03-filt | ||
66 | SWAP | ||
67 | BACK | ||
68 | |||
69 | |||
70 | MENU Hugs | ALL | BLUE | PINK | ||
71 | TOMENU Sit hugs | ||
72 | TOMENU Stand hugs | ||
73 | TOMENU Lay hugs | ||
74 | BACK | ||
75 | |||
76 | |||
77 | MENU Stand hugs | ALL | BLUE | PINK | ||
78 | POSE Big kiss | long-kiss-masculine | kiss | ||
79 | POSE Hug | HUG | HUG | ||
80 | //POSE Lovers 5 | lovermale5 | lovefemale5a | ||
81 | //POSE Lovers 14 | lovermale14 | lovefemale14 | ||
82 | //POSE Hug | hug-feminine | hug-masculine | ||
83 | //POSE Lovers 1 | lovermale1 | lovefemale1 | ||
84 | //POSE Lovers 2 | lovermale2 | lovefemale2 | ||
85 | SWAP | ||
86 | BACK | ||
87 | |||
88 | |||
89 | MENU Sit hugs | ALL | BLUE | PINK | ||
90 | //POSE Relax | flay6 | flay18 | ||
91 | //POSE Lovers 20 | lovermale20 | lovefemale20b | ||
92 | //POSE Lovers 23 | mslmale23a | mslfemale23b | ||
93 | //POSE Lovers 29 | mslmale29 | mslfemale29 | ||
94 | //POSE Lovers 3 | lovermale3b | lovefemale3b | ||
95 | //POSE Lovers 4 | lovermale4 | lovefemale4 | ||
96 | //POSE Lovers 7 | lovemale7e | lovefemale7 | ||
97 | //POSE Chat | sit on ground m retime 90 M pr2 | sit on ground F v2 retime 90 F | ||
98 | //POSE Kiss | Ground_Kiss_M | Ground_Kiss_F | ||
99 | POSE Cradle her | cpose10 v5 M | cpose10 v6 F | ||
100 | SWAP | ||
101 | BACK | ||
102 | |||
103 | |||
104 | MENU Lay hugs | ALL | BLUE | PINK | ||
105 | //POSE Embrace | Laying_Arm_Across_M | Laying_Arm_Across_F | ||
106 | //POSE Gaze | LS 2 static M | LS 2 static F | ||
107 | //POSE Lay | laying_arm_across_f | laying_arm_across_m | ||
108 | //POSE Lay kiss | Laying_Pinned_Kiss_M | Laying_Pinned_Kiss_F | ||
109 | //POSE Lay on side | cpose3v4 m | cpose3v4 f | ||
110 | //POSE Lovers 1a | csmale1 | csfemale1a | ||
111 | POSE Make out | laying_makeout_m | laying_makeout_f | ||
112 | //POSE Neck | Laying_Neck_Kiss_M | Laying_Neck_Kiss_F | ||
113 | POSE Pinned | laying_pinned_m | laying_pinned_f | ||
114 | //POSE Prop | Laying_Propped_Arm_M | Laying_Propped_Arm_F | ||
115 | //POSE Reflect | couchfidget 1 | couchlay2 f2 | ||
116 | //POSE Rest | lusirestkr5 | massage receiver | ||
117 | //POSE Side | Laying_Side_M | Laying_Side_F | ||
118 | //POSE Spoon | Laying_Spoon_M | Laying_Spoon_F | ||
119 | POSE Snuggle him | couple pose 7 v4 M | couple pose 7 v4 F | ||
120 | SWAP | ||
121 | BACK | ||
122 | |||
123 | |||
124 | |||
125 | MENU Lick girl | ALL | BLUE | PINK | ||
126 | //POSE 69 | 69_M | 69_F | ||
127 | //POSE Lick me | ASK_k_43_M_(BA_bundle) | ASK_k_43_F_(BA_bundle) | ||
128 | POSE Taste | rimm | rimf | ||
129 | POSE Lick her | 1licker | 1lickeee | ||
130 | SWAP | ||
131 | BACK | ||
132 | |||
133 | |||
134 | MENU Lick boy | ALL | BLUE | PINK | ||
135 | //POSE 69 | 69_M | 69_F | ||
136 | //POSE BlowJob 1 | BJ_M | BJ_F | ||
137 | SWAP | ||
138 | BACK | ||
139 | |||
140 | |||
141 | MENU Boy on top | ALL | BLUE | PINK | ||
142 | //POSE Behind | Chair_M | Chair_F | ||
143 | POSE Deckchair | Deckchair position-m | Deckchair position-f | ||
144 | POSE Eagle | Spread Eagle-m | Spread Eagle-f | ||
145 | //POSE Missionary | Missionary_M | Missionary_F | ||
146 | //POSE So hard! | Kaly_Kam58 M_3_ADV | Kaly_Kam58 F_1_ADV | ||
147 | SWAP | ||
148 | BACK | ||
149 | |||
150 | |||
151 | MENU Girl on top | ALL | BLUE | PINK | ||
152 | POSE Butterfly | Butterfly position-m | Butterfly position-f | ||
153 | //POSE Cowgirl | Rub_M | Lay_F | ||
154 | POSE Cowgirl 2 | Cowgirl-m | Cowgirl-f | ||
155 | //POSE Ride 1 | Ride_M | Ride_F | ||
156 | //POSE Ride 2 | RideB_M | RideB_F | ||
157 | //POSE Ride 3 | Ground_M | Ground_F | ||
158 | //POSE Ride me 1 | ASK_k_43bis_M_(BA_bundle) | ASK_k_43_F_(BA_bundle) | ||
159 | SWAP | ||
160 | BACK | ||
161 | |||
162 | |||
163 | MENU Side by side | ALL | BLUE | PINK | ||
164 | POSE Side Entry | Side Entry Missionary-m | Side Entry Missionary-f | ||
165 | POSE Spoon 2 | Spoons Position-m | Spoons Position-f | ||
166 | SWAP | ||
167 | BACK | ||
168 | |||
169 | |||
170 | MENU Stand sex | ALL | BLUE | PINK | ||
171 | //POSE Doggy 1| Doggy_M | Doggy_F | ||
172 | POSE Doggy Style | Doggy Style-m | Doggy Style-f | ||
173 | POSE Leapfrog | Leapfrog Position-m | Leapfrog Position-f | ||
174 | //POSE Lifted | Table_M | Table_F | ||
175 | //POSE Post 1 | Wall_M | Wall_F | ||
176 | //POSE Post 2 | Wall2_M | Wall2_F | ||
177 | POSE Standing Assfuck | Take from behind standing-m | Take from behind standing-f | ||
178 | SWAP | ||
179 | BACK | ||
180 | |||
181 | |||
182 | |||
183 | MENU Options >> | OWNER //this menu can be accessed by the OWNER only (other options: GROUP / ALL) | ||
184 | SHOW Show | ||
185 | HIDE Hide | ||
186 | ADJUST Adjust Pos //changes poseballs into transparant beams easy to select for moving | ||
187 | Z+1 //adjust Z = height offset in cm - use any integer to set the step size | ||
188 | Z+10 | ||
189 | SAVE Save Pos //saves the poseball positions of the currently selected pose into memory | ||
190 | Z-1 //adjust Z = height offset (so you don't have to adjust the positions of | ||
191 | Z-10 // each individual pose for different bodies/places) | ||
192 | DUMP Dump Pos //lists all positions stored in memory, copy/paste into .POSITIONS for backup | ||
193 | TOMENU ShutDown >> | ||
194 | BACK | ||
195 | LINKMSG Save Prop | 0,-4,1,SAVEPROP // save position/rotation for a prop | ||
196 | LINKMSG Dump Props | 0,-4,1,DUMPPROPS // dump all prop configs | ||
197 | REDO Redo Menu | ON | ||
198 | CHAT Chat Info | ON //switches chat info ON/OFF | ||
199 | INVISIBLE Invisible //make the main object invisible/visible (usefull if it's worn) | ||
200 | BALLUSERS Ball Users | ALL //switches who can sit on the poseballs (ALL/GROUP) | ||
201 | MENUUSERS Menu Users | ALL //switches who access main menu (ALL/GROUP/OWNER) | ||
202 | BACK | ||
203 | |||
204 | |||
205 | MENU ShutDown >> | OWNER | ||
206 | RELOAD Pos Reset // use after changing *.POSITIONS* or *.PROPS* files | ||
207 | CHECK ConfigCheck // check config consistency. NOTE: does a Pos Reset when done! | ||
208 | RESET Menu Reset // use after changing *.MENUITEMS* files | ||
209 | RESTART Restart | ||
210 | OFF ShutDown | ||
211 | BACK | ||
diff --git a/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/.POSITIONS b/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/.POSITIONS new file mode 100644 index 0000000..0d55a63 --- /dev/null +++ b/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/.POSITIONS | |||
@@ -0,0 +1,24 @@ | |||
1 | [10:01] : {default} <-.7,.7,0.> <-90.,0.,-180.> <.7,.7,0.> <-90.,0.,-45.> <0.,.7,.7> <-90.,0.,-90.> <0.,.7,-.7> <-90.,0.,90.> <.7,.7,-.7> <-90.,0.,45.> <-.7,.7,.7> <-90.,0.,-135.> | ||
2 | [10:01] : {stand} <-.7,.7,0.> <-90.,0.,-180.> <.7,.7,0.> <-90.,0.,-45.> <0.,.7,.7> <-90.,0.,-90.> <0.,.7,-.7> <-90.,0.,90.> <.7,.7,-.7> <-90.,0.,45.> <-.7,.7,.7> <-90.,0.,-135.> | ||
3 | [10:01] : {sit2} <-0.355,0.660,-0.584> <-97.0,0.0,-90.0> <0.508,0.700,-0.579> <-95.5,0.0,90.0> | ||
4 | [10:01] : {pillow-sit} <-0.355,0.660,-0.584> <-97.0,0.0,-90.0> <0.508,0.700,-0.579> <-95.5,0.0,90.0> | ||
5 | [10:01] : {standing} <-0.700,1.009,0.000> <-90.0,0.0,0.0> <0.700,1.009,0.000> <-90.0,0.0,-180.0> | ||
6 | [10:01] : {6way-1} <-0.700,0.700,0.000> <-90.0,0.0,90.0> <0.700,0.700,0.000> <-90.0,0.0,90.0> <-1.111,0.675,0.000> <-90.0,0.0,90.0> <0.000,0.696,0.000> <-90.0,0.0,90.0> <1.058,0.665,0.000> <-90.0,0.0,90.0> <1.305,0.658,0.000> <-90.0,0.0,90.0> | ||
7 | [10:01] : {6way-2} <-0.700,0.700,0.000> <-90.0,0.0,-180.0> <0.700,0.700,0.000> <-90.0,0.0,-45.0> <0.000,0.700,0.700> <-90.0,0.0,-90.0> <0.000,0.700,-0.700> <-90.0,0.0,90.0> <0.698,0.699,-0.675> <-90.0,0.0,45.0> <-0.701,0.699,0.702> <-90.0,0.0,-135.0> | ||
8 | [10:01] : {Butterfly} <0.081,0.086,0.065> <178.0,0.0,0.0> <-0.096,0.064,0.203> <178.0,0.0,0.0> | ||
9 | [10:01] : {Cowgirl 2} <0.372,0.037,0.078> <2.6,-89.0,0.3> <0.163,0.041,0.180> <2.6,-89.0,0.3> | ||
10 | [10:01] : {Deckchair} <0.085,-0.015,0.292> <0.0,-89.0,-0.7> <0.305,-0.005,0.272> <-180.0,-89.0,-179.3> | ||
11 | [10:01] : {Doggy Style} <-0.204,0.021,0.607> <0.9,-87.0,0.9> <-0.11,0.005,0.379> <0.0,-87.0,0.0> | ||
12 | [10:01] : {Eagle} <0.118,-0.051,0.475> <180.0,-85.0,-179.3> <0.375,-0.083,0.414> <180.0,-88.0,-179.3> | ||
13 | [10:01] : {Leapfrog} <-0.203,-0.002,0.437> <0.0,-90.0,0.0> <-0.08,-0.014,0.241> <0.0,-90.0,0.0> | ||
14 | [10:01] : {Side Entry} <-0.173,0.081,0.511> <0.0,-85.0,0.7> <-0.108,0.238,0.546> <84.9,-13.9,89.5> | ||
15 | [10:01] : {Spoon 2} <0.241,0.247,0.337> <180.0,-84.4,-179.3> <0.195,0.453,0.368> <-144.7,-83.1,-143.8> | ||
16 | [10:01] : {Standing Assfuck} <-0.814,0.163,0.258> <-179.0,-76.0,0.0> <-0.741,0.174,0.012> <-179.0,-73.0,0.0> | ||
17 | [10:01] : {Big kiss} <-0.656,-0.058,0.029> <0.0,-86.6,0.0> <-0.829,0.047,0.452> <19.7,-82.9,-170.5> | ||
18 | [10:01] : {Make out} <-0.638,0.003,0.39> <73.6,-87.9,78.5> <-0.565,-0.841,0.205> <-65.1,-88.4,-65.5> | ||
19 | [10:01] : {Taste} <-0.679,0.012,0.201> <147.9,-87.4,147.6> <-1.004,-0.035,-0.542> <159.5,-82.6,-18.2> | ||
20 | [10:01] : {Lick her} <-0.599,-0.02,0.812> <-123.7,-86.4,146.4> <-0.46,-0.032,-0.16> <-179.8,-86.4,-78.7> | ||
21 | [10:01] : {Cradle her} <-0.273,0.009,0.000> <0.0,-88.0,0.0> <-0.405,0.046,0.098> <0.0,-86.0,0.0> | ||
22 | [10:01] : {Snuggle him} <-0.205,-0.246,0.091> <-84.2,-87.6,-87.7> <-0.27,-0.063,-0.034> <-93.6,-87.6,176.3> | ||
23 | [10:01] : {Pinned} <-0.664,-0.008,0.098> <-90.7,-86.9,-91.6> <-0.816,-0.739,-0.052> <-171.0,-78.5,-169.2> | ||
24 | [10:01] : {Hug} <-0.859,-0.078,-0.082> <-173.9,-82.9,-170.9> <-0.471,0.000,0.272> <53.9,-88.3,-129.1> \ No newline at end of file | ||
diff --git a/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/.PROPS.example b/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/.PROPS.example new file mode 100644 index 0000000..e76c9bf --- /dev/null +++ b/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/.PROPS.example | |||
@@ -0,0 +1 @@ | |||
| pillow-sit | pillow | <0.000,0.266,-0.656>/<0.000,-90.000,15.981> \ No newline at end of file | |||
diff --git a/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/.SEQUENCES.example b/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/.SEQUENCES.example new file mode 100644 index 0000000..fcc1318 --- /dev/null +++ b/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/.SEQUENCES.example | |||
@@ -0,0 +1,48 @@ | |||
1 | / Sequence config for MLPV2.3 | ||
2 | / lines beginning with slash are comments | ||
3 | |||
4 | / Global commands (these are commented out) | ||
5 | / Use any number of these by deleting the slash at the beginning | ||
6 | / debug | 1 | sequence start/stop | ||
7 | / debug | 2 | echo each command as executed | ||
8 | / debug | 4 | avatar hop on/off | ||
9 | / debug | -1 | all debugging | ||
10 | |||
11 | / Sequence Commands: | ||
12 | / ======= | ||
13 | / SEQUENCE | seqence-name | ||
14 | / MENU | menu-name | set number & colors of balls | ||
15 | / POSE | pose-name | chat-chan | chat-message | start a pose (chan & message are optional; message is whispered). | ||
16 | / AVWAIT | 0 1 2 3 | chat-message-if-waiting | pause the sequence until the balls listed are sat on (0 1 2 3 in this example) | ||
17 | / SAY | chat-chan | chat-message | say the given text on the given chat chan | ||
18 | / WHISPER | chat-chan | chat-message | whisper the given text on the given chat chan | ||
19 | / WAIT | wait-seconds | pause before executing next command | ||
20 | / LABEL | label-name | set a target for GOTO | ||
21 | / GOTO | label-name | go to a label, to loop the bottom of a sequence | ||
22 | / REPEAT | repeat the whole sequence | ||
23 | |||
24 | / Chat-messages can include the first names of participants using /0 for avatar on first ball, /1 for av on 2nd ball, etc. | ||
25 | / (See the names of the ball objects.) | ||
26 | |||
27 | SEQUENCE | Tour1 | ||
28 | MENU | Example... | ||
29 | POSE | standing | ||
30 | AVWAIT | 0 | Waiting for someone to sit on blue ball | ||
31 | WHISPER | 0 | /0 and /1 stand together | ||
32 | WAIT | 10 | ||
33 | POSE | pillow-sit | 0 | /0 and /1 sit with a comfy pillow | ||
34 | WAIT | 10 | ||
35 | POSE | sit2 | 0 | The pillow disappears | ||
36 | WAIT | 10 | ||
37 | REPEAT | ||
38 | |||
39 | SEQUENCE | tour2 | ||
40 | MENU | Example... | ||
41 | POSE | standing | 0 | The two of you stand | ||
42 | WAIT | 10 | ||
43 | LABEL | here | ||
44 | POSE | pillow-sit | 0 | /0 and /1 sit with a pillow | ||
45 | WAIT | 10 | ||
46 | POSE | sit2 | 0 | Where did the pillow go? | ||
47 | WAIT | 10 | ||
48 | GOTO | here | ||
diff --git a/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/.readme b/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/.readme new file mode 100644 index 0000000..182545b --- /dev/null +++ b/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/.readme | |||
@@ -0,0 +1,287 @@ | |||
1 | MLPV2 Version 2.3, by Learjeff Innis, based on | ||
2 | MLP - MULTI-LOVE-POSE V1.2 - Copyright (c) 2006, by Miffy Fluffy (BSD License) | ||
3 | |||
4 | OpenSim port by Jez Ember. This should be fully functional, and works around various scope changes and bugs in OS LSL. Don't take this back to SL - pick up the regular release there. | ||
5 | |||
6 | The BSD Licence allows anybody to use the source code, in any manner they wish, providing that they provide the copyright notice above on further distributions. | ||
7 | So it's totally free, however if you like it, I would be very happy if you donate any L$. If you're using significant parts of this code in commercial products, I would appreciate if you donate me at least L$1 for each sold product (preferably more :). And it's nice if you could send me a copy of each commercial product, incl. updates (as I do get a lot of questions from buyers of commercial products made with the MLP, also please indicate who to contact, not me :) | ||
8 | I won't give support, however I'll make an exception for end-users that donated L$1000 or more (for commercial support, custom versions, contact me, however my time is limited). | ||
9 | To donate, go to my profile (Search - People - Miffy Fluffy) and use the "Pay..." button, thanks! | ||
10 | You can also find the link to the latest version here. | ||
11 | |||
12 | Please feel free to donate to Learjeff Innis for the MLPV2 enhancements. My thanks to Miffy Fluffy for the original! Find MLPV2 scripts for L$1 at http://XStreetSL.com . | ||
13 | |||
14 | FEATURES: | ||
15 | - Put all your poseball animations into one object (50 pairs or even more should be no problem). | ||
16 | - Create submenus for each category of poses, for instance: "Solo, Boy-Girl, Girl-Girl, Dance, 3some, 4some" | ||
17 | - Shows 1, 2, 3, or 4 poseballs depending on the submenu you select | ||
18 | - Positions can be adjusted and saved into memory (backup is easy: select Memory Dump and copy-paste into notecard) | ||
19 | - Portable, can be worn and used everywhere | ||
20 | - Option to adjust height offset (Z) of all poses at once (for different persons/locations). | ||
21 | - 15 poseball colors: | ||
22 | PINK, BLUE, PINK2, BLUE2, GREEN, MAGENTA, RED, ORANGE, WHITE, BLACK, YELLOW, CYAN, RED2, TEAL, GREEN2 | ||
23 | |||
24 | OPERATION: | ||
25 | - Click the MLP object to switch it on | ||
26 | - When everything has loaded click again for the menu | ||
27 | - Select a submenu containing poses, and select a pose. Poseballs will appear. | ||
28 | - Sit on your poseball (Right-click - LOVE) | ||
29 | - Accept the popup asking permission to animate your avatar. (Might be behind the MLP menu, click ">>>" to see.) | ||
30 | - To disable expressions, use Page Down key. To re-enable them, use Page Up. This only affects you and not people on other poseballs. Expressions are re-enabled by default when anyone else sits on the poseball. | ||
31 | - To remove the balls, select 'STOP'. | ||
32 | |||
33 | |||
34 | TO ADJUST POSITIONS: | ||
35 | You can adjust the poses to fit your own avatar and those you share MLP with. | ||
36 | - Select a pose you want to adjust and sit on the balls. | ||
37 | - Go back to the main menu, select "Options - Adjust Pos". This changes the balls into transparant beams. | ||
38 | - Right-click a beam, select Edit and adjust the position (Shift-click to select more than one). | ||
39 | - Position the balls anywhere within 10m from the MLP object. | ||
40 | - "Save Pos" stores the position into memory. | ||
41 | - Important! Back it up; see below. | ||
42 | |||
43 | TO MAKE A BACKUP: | ||
44 | Saved positions are stored in memory but are not permanent. They are lost on script error (See "Script run-time error / Stack-Heap Collision" below). They are also lost on shutdown/startup, or "Pos Reset". To back the positions up more permanently you have to copy them into the .POSITIONS notecard: | ||
45 | - Select "Mem Dump" | ||
46 | - Copy the complete dump (from Chat-History) | ||
47 | - Paste it into the .POSITIONS notecard (just replace everything, you don't need to edit/format anything). | ||
48 | - Delete any other *.POSITIONS* files. | ||
49 | |||
50 | Note: After changing any *.POSITIONS* files, use the "Pos Reset" command to verify your changes, if desired. This also helps to avoid losing changes due to Stac-Heap collisions. | ||
51 | |||
52 | TO ADJUST HEIGHT OFFSET (Z): | ||
53 | Select "Height Adj" and click the "Z"-buttons, this will adjust the height for all poses. | ||
54 | Note: the offset height is stored in the Object Description, so any descriptions will be replaced. | ||
55 | |||
56 | TO ADD POSES: | ||
57 | Copy all animations into the MLP object (if you want to use existing poseballs, open them to rip their animations). Note: you can use any object as MLP, just copy the MLP contents in the object of your choice. | ||
58 | Open the .MENUITEMS and add the animations: | ||
59 | POSE name | animation1 | animation2 ... | ||
60 | The changes will become active after MLP is (re)started. Use the "Menu Reset" command after changing *.MENUITEMS* files. | ||
61 | |||
62 | To give an expression to an animation, add one of the following suffixes to the anim name in the POSE line. | ||
63 | (Just add it to the POSE config line, don't change the anim name.) | ||
64 | |||
65 | Suffix / expression | ||
66 | * open mouth | ||
67 | ::1 open mouth | ||
68 | ::2 surprise | ||
69 | ::3 tongue out | ||
70 | ::4 smile | ||
71 | ::5 toothsmile | ||
72 | ::6 wink | ||
73 | ::7 cry | ||
74 | ::8 kiss | ||
75 | ::9 laugh | ||
76 | ::10 disdain | ||
77 | ::11 repulsed | ||
78 | ::12 anger | ||
79 | ::13 bored | ||
80 | ::14 sad | ||
81 | ::15 embarrassed | ||
82 | ::16 frown | ||
83 | ::17 shrug | ||
84 | ::18 afraid | ||
85 | ::19 worry | ||
86 | ::20 sleeping (combination of disdain and smile, closest I could find) | ||
87 | |||
88 | To make the expression happen periodically rather than constantly, add another extension and the period (in seconds). | ||
89 | |||
90 | For example, to use MyAnim with open mouth every 5.5 seconds: | ||
91 | |||
92 | POSE Mypose | MyAnim::1::5.5 | ||
93 | |||
94 | TO ADD SOUNDS (buttons to play sounds), in a menu (just like a POSE button), add a line like this: | ||
95 | |||
96 | SOUND She moans | female-moan | ||
97 | |||
98 | where "She moans" will be the button label, and "female-moan" is the animation to play, which must be in object inventory. | ||
99 | For sounds in menus with poses (rather than in a menu specifically for sounds) I recommend you begin the pose name with "☊" (which looks a bit like headphones, the best I could find for the purpose). This serves as a clue to the user that the button plays a sound. | ||
100 | |||
101 | TO CREATE ANIMATION SETS (menus) | ||
102 | Create .MENUITEMS.xxx and .POSITIONS.xxx files (where xxx is whatever you want) and put the corresponding menu configs and poses in them. This way you can deliver a bed with folders of add-on menus so the customer can choose what types of anims they want to add to the menu. Note that you get at most 12 top menu choices. The scripts read the .POSITIONS files in alphabetical order (and .POSITIONS must be first). The menus are assembled in the usual SL ass-backwards-by-three manner. | ||
103 | |||
104 | This also allows you to sell furniture with "enhancement packs", which are simply collections of .MENUITEMS.xxx, .POSITIONS.xxx, and the associated animations for the customer to drop into the furniture. Customers can easily select furniture appearance and pose bundles independently! | ||
105 | |||
106 | Note for those who are adding animation sets to MLP V1.2 configurations: For this feature to work, there must be "TOMENU -" entries in the main menu. These are very easy to add to an existing configuration, just delete all "TOMENU" lines in the main menu and replace them with "TOMENU -" lines. Also, add a "MENUORDER" to the .MENUITEMS file. Now, all MENU configs that don't have a corresponding "TOMENU" entry will be put in the main menu, replacing a blank one. Unused blank ones are deleted automatically. See the .MENUITEMS file from the MLPV2 release for more info. | ||
107 | |||
108 | ACCESS TO THE MAIN MENU: | ||
109 | The owner is the only one who can start/restart/shutdown, in all cases. | ||
110 | - if "Options - MenuUser" is set to OWNER: the owner is the only one who can access the menus | ||
111 | - if "Options - MenuUser" is set to ALL: anyone can access the MAIN MENU | ||
112 | - if "Options - MenuUser" is set to GROUP: members of the same Group as the MLP object can access the MAIN MENU (the MLP Group can set by right-clicking MLP and selecting Edit, More >> General tab - Group: Set) | ||
113 | Note: even if "MenuUser" is set to ALL or GROUP, individual SUBMENUS can still be blocked (you can define access for each submenu in .MENUITEMS, see examples in .MENUITEMS). | ||
114 | |||
115 | POSEBALL ACCESS: | ||
116 | - if "Options - BallUsers" is set to ALL: anyone can sit on the ball | ||
117 | - if "Options - BallUsers" is set to GROUP: only groupmembers can sit on a poseball. The balls will check if the person who tries to sit on the ball belongs to the same Group as the ~ball object (to set the Group of the ball, take a new copy of the MLP with your preferred Group set active on you. You could also take the ~ball out of the MLP, into the world, right-click, Edit, More >> General tab - Group: Set, thereafter take the edited ~ball into your Inventory (note: do this within a minute or so, because balls commit suicide after a while when taken into the world), delete the old ~ball in the MLP, and drag the new ~ball from your Inventory to the MLP). | ||
118 | |||
119 | PORTABLE USE: | ||
120 | Attach the object to the HUD, you can use it's default shape and color for clickable bar on one of the edges of your screen (to move HUD position: Right-click - Edit), you can edit color/transparancy/size/position. | ||
121 | Adjust the height offset (Z). Note: the balls will appear relative to the initial MLP position (to reset where the balls appear, press STOP to remove the balls. and reselect a submenu to rez them again). | ||
122 | |||
123 | ================================================ | ||
124 | |||
125 | FAQ for END USERS: | ||
126 | - Why do I hover, sitting, after sitting on a poseball? | ||
127 | Be sure to answer "Yes" to the popup that asks permission to animate your avatar. This is often buried under the MLP main menu, so click the ">>>" to cycle through menus. This is SL behavior and there's no way to fix it, other than turning "remenu" off. | ||
128 | |||
129 | - Will my animations be lost if I lose a poseball? | ||
130 | No. The animations are not placed the balls, they remain in the main MLP object. Don't worry about the poseballs, they are copies of the one in the MLP object. A balls will commit suicide if left behind somewhere (the MLP object needs to be within 20m). | ||
131 | |||
132 | - Sometimes notecards or scripts won't open for editing, why? | ||
133 | If the MLP contains many animations, access to it's contents can be slow, try again after a few seconds. | ||
134 | |||
135 | - "Script run-time error / Stack-Heap Collision"? | ||
136 | Right-click/Edit the object, and use SL menu: "Tools -> Reset Scripts in Selection" to reset. | ||
137 | Any saved positions that were not backed up in .POSITIONS files are lost, so if your furniture has lots of poses (over 50) and you save positions, be sure to back up regularly. Use OPTIONS -> Pos Reset after changing .POSITIONS* files. | ||
138 | |||
139 | FAQ for those who edit *.MENUITEMS files: | ||
140 | |||
141 | - "Script run-time error / Stack-Heap Collision"? | ||
142 | After a restart, this is a clue that there are too many items in *.MENUITEMS* or *.POSITIONS* files. Trim the menu, or pray for Mono to arrive soon. | ||
143 | |||
144 | - My new menu appears on the main page, rather than as a submenu where I configured it. Why? | ||
145 | Most likely, you named it differently in the MENU line versus the TOMENU line. When MPL sees a MENU line, it looks for the same name in a TOMENU line. If it doesn't find it, it replaces any "TOMENU -" entries it finds, generally on the main menu. | ||
146 | |||
147 | |||
148 | ================================================ | ||
149 | 2.3l: fixed prim/script ownership, fixed ball listening on old channels, fixed prop jumping when saved twice | ||
150 | 2.3k: fixed startup race condition (stopping before reading MENUITEMS), fixed sequence labels not found | ||
151 | 2.3j: height menu bug fix (probably broken since 2.3's reorient menu added) | ||
152 | 2.3i: bug fix (remenu broken in 2.3h) | ||
153 | 2.3h: sequences: rez balls on sequence start | ||
154 | 2.3g: reset fixes: | ||
155 | - kill balls on reset in ~menu startup | ||
156 | - don't say "click to start" until ready, in ~run | ||
157 | ================================================ | ||
158 | |||
159 | CHANGES in MLPV2 Version 2.3: | ||
160 | |||
161 | - Supports sounds | ||
162 | |||
163 | - Supports up to 6 avatars (poseballs) | ||
164 | |||
165 | - Sequences (tours) -- set up a menu button that plays a sequence of poses and chats. You configure the sequences in a new .SEQUENCE type of notecard. More info on that here: | ||
166 | |||
167 | ? | ||
168 | |||
169 | - When rezzed, balls are now named ~ball0 .. ~ball5, to support easy sitting for bot clients (used for machinima, not camping!) The object name in inventory has not changed. | ||
170 | |||
171 | - "Adjust Pos" is now a toggle. Try it and see! Avs can hop on and off and balls return to the 'adjusting' shape. You can also use STOP to return to normal mode. | ||
172 | |||
173 | - EZ-Adust! Now, when you're in adjust mode and you change poses, it saves the current pose before swithcing to new pose. To abandon changes, quit adjust mode, STOP, or just re-select the current pose. | ||
174 | |||
175 | - Tools pack: | ||
176 | - "Reorient" menu for more easily adapting an existing pose set to a new furniture item | ||
177 | - script to check anim permissions | ||
178 | - script to check for unused animations | ||
179 | - Three different example xcite adaptor scripts (requires Xcite! Partner script from Xcite) | ||
180 | - AutoZhao adaptor script | ||
181 | - touch passer moved here, since it's never required in the MLP prim | ||
182 | |||
183 | ================================================ | ||
184 | |||
185 | CHANGES in MLPV2 Version 2.2 (unreleased other than to MLPV2 group) | ||
186 | |||
187 | - Added LMs when avs sit or unsit, to make it possible to add support for things like xcite and cuffs without modifying MLP scripts. Read more here: | ||
188 | |||
189 | ? | ||
190 | |||
191 | - Cleaner chat on DUMP (omits object name) | ||
192 | |||
193 | ================================================ | ||
194 | |||
195 | CHANGES in MLPV2 Version 2.1: | ||
196 | |||
197 | - Props! Rez an object per pose. Object is deleted when changing to new pose, or after 3 minutes if bed is deleted. | ||
198 | |||
199 | - 15 ball colors supported! | ||
200 | |||
201 | - AUTOBACK - automatically inserts BACK before MORE--> button (optional, off by default) | ||
202 | |||
203 | - Bug fix for AUTOMORE on main menus with too many buttons. AUTOMORE no longer supported for main menu. Might be fixed some day. | ||
204 | |||
205 | - Bug fix for AUTOMORE menues with more than one extra page. | ||
206 | |||
207 | - Expression control code removed -- didn't work out. MLPV2 no longer takes controls. | ||
208 | |||
209 | Of course, still compatible with all MLP and MLPV2.0 scripts. | ||
210 | |||
211 | ================================================ | ||
212 | |||
213 | CHANGES in MLPV2, Version 2.0: | ||
214 | |||
215 | - Now supports Solo, 3some, and 4some menus. | ||
216 | |||
217 | - Memory optimized: now holds over 70 couples poses. | ||
218 | |||
219 | - Expressions supported (20 expressions, constant or periodic). See "TO ADD POSES" above. | ||
220 | |||
221 | - Extended menus. (Automatic "More-->" button for menus with more than 12 buttons.) | ||
222 | |||
223 | - Menu buttons now appear in menus in the same order as in the configuration | ||
224 | (but only if the new MENUORDER config item appears -- otherwise order is same as before, for backwards compatibility). | ||
225 | |||
226 | - Modular configuration: reads all *.MENUITEMS* and *.POSITIONS* files, in sort order (same as in object contents). | ||
227 | MENU config lines with no corresponding TOMENU lines get added to the main menu (replacing a blank "TOMENU -" line). | ||
228 | This allows makers to easily provide add-on packs, each being folder containing .MENUITEMS*, .POSITIONS*, and animations files. | ||
229 | Customer simply drops the folder in and resets. | ||
230 | |||
231 | - Backwards-compatible with MLP V1.2 configurations. | ||
232 | |||
233 | - Ball timeouts have been disabled. This should make MLPV2 a little more efficient. | ||
234 | However, if you move a bed with balls rezzed, you'll need to delete the balls manually. | ||
235 | |||
236 | - Set poseball's floating text and pie menu sit text by changing its description. | ||
237 | Also, if the ball's description begins with an asterisk ("*"), the poseball is phantom. | ||
238 | After changing ball's description, STOP to delete any balls and then select any pose. | ||
239 | |||
240 | - New LM button type, to pass LMs to other scripts/prims. | ||
241 | This allows adding features to furniture, with buttons in the MLP menus, without changing any MLP scripts. | ||
242 | |||
243 | - Warning for duplicate entries in .POSITIONS* files. | ||
244 | |||
245 | - Configuration consistency checker: try "ConfigCheck" in Shutdown menu | ||
246 | NOTE: this will reload .POSITIONS.* files, so backup any saved positions first! | ||
247 | It will find buttons with no positions and vice versa. | ||
248 | |||
249 | - AutoZhao support | ||
250 | |||
251 | - Restart menu reorganized: | ||
252 | Use "Pos Reset" button after changing *.POSITIONS* files. | ||
253 | Use "Menu Reset" button after changing *.MENUITEMS* files. | ||
254 | Use "Restart" button to restart all. This used to do only a menu reset. | ||
255 | |||
256 | - MLP bug fix: if you rez a copy, it uses the same channel as the original, and on MLP V1.2 you'd get crosstalk. | ||
257 | The menu script is now reset on rez. This does not reset positions; saved positions are not lost. | ||
258 | |||
259 | - MLP bug fix: Avoid reanimating a non-sitting avatar! This happened in these cases that I'm aware of: | ||
260 | A) Avatar is posed and STOP button is hit and then a new pose is selected. The avatar (no longer sitting) would get animated. | ||
261 | B) Same as above, but instead of STOP button, avatar teleports or relogs | ||
262 | |||
263 | |||
264 | |||
265 | CHANGES IN MLP V1.2: | ||
266 | - now checks if the balls are rezzed, it will rez new balls after a ball has disappeared unexpectedly for some reason (after a few minutes) | ||
267 | - ownership change is detected (thanks to Kokoro Fasching) | ||
268 | - added STAND button (now different from STOP button), to avoid confusion. STAND will always set the default stand pose. STOP will always remove the balls. | ||
269 | - added GROUP access option to MAIN MENU, in the Options menu - 'MenuUser' you can select between OWNER/GROUP/ALL (previous users need to adjust their .MENUITEMS notecard, USERS has become MENUUSERS with the new options). | ||
270 | - added GROUP access option for each individual SUBMENU, in .MENUITEMS you can define the access restriction for each submenu: OWNER/GROUP/ALL. | ||
271 | - added GROUP access option for the poseballs, In the Options menu - 'BallUsers' you can select between GROUP/ALL. | ||
272 | - If you select the menu while it has been used by someone else within the last minute, you're asked if you want to continue. (In previous versions the owner did get a chat message if any user operated the menu, this has been removed. To add this feature again: uncomment line #51 in ~menu.) | ||
273 | - note: menu's and poses can not have the same name anymore, users of previous versions should change the name of the 'Shut Down' button to something else (f.i: ShutDown!) if they also have a menu with the same name. | ||
274 | |||
275 | CHANGES IN MLP V1.11: | ||
276 | - fixed a mistake I made which caused the balls to dissappear within 60 seconds. | ||
277 | |||
278 | CHANGES IN MLP V1.1: | ||
279 | - adjusted sit height on the balls, so the balls will remain visible with most objects | ||
280 | - altough not really necessary, I've added the possibility to SHOW/HIDE the balls via the menu (you can add a SHOW and/or HIDE button somewhere in the .MENUITEMS notecard) | ||
281 | - improved menuacces: selections from previous menudialogs will be disregarded (avoids problems with multiple users too) | ||
282 | - reduced load: no timers are running anymore when no balls are rezzed | ||
283 | |||
284 | |||
285 | Please report any bugs, or improvements in efficiency without losing readability of the code (In many instances I've chosen readabilty over speed or size because I think it's reasonable to expect that the compiler will improve in the future). If you want to read the code start reading the comments in ~run for an overview. The source code used in ~menu is partly based on the Menu Engine by Zonax Delorean (BSD License), thanks. I included some free poses as examples, thanks to their makers. Thanks to Purrcat Miranda for testing with me :) Thanks to other creative people in SL too, and thanks for any donations. Have fun! | ||
286 | |||
287 | MLP - MULTI-LOVE-POSE V1.2 - Copyright (c) 2006, by Miffy Fluffy (BSD License) \ No newline at end of file | ||
diff --git a/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/index.omg b/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/index.omg new file mode 100644 index 0000000..a2dcaad --- /dev/null +++ b/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/index.omg | |||
@@ -0,0 +1,20 @@ | |||
1 | nc .MENUITEMS | ||
2 | nc .POSITIONS | ||
3 | nc .PROPS.example | ||
4 | nc .SEQUENCES.example | ||
5 | nc .readme | ||
6 | obj ~ball | ||
7 | lsl 344fe8d3-97c9-4fec-ab70-a121266a6539 ~memory | ||
8 | lsl 025b80de-b8de-4571-b699-190bf906c134 ~menucfg | ||
9 | lsl a22de921-3ccd-4005-9ecc-ef8bb1201b7c ~menu | ||
10 | lsl 41e4b1ad-3153-4d8a-8c0a-42bb79345dce ~pose | ||
11 | lsl 04dae926-3663-477d-bcac-ff38ef3fd34d ~poser 1 | ||
12 | lsl 0813b7fb-0641-4831-9531-654da1361ae5 ~poser 2 | ||
13 | lsl 2fc4e9bb-087f-4e1a-b019-fce70d715151 ~poser 3 | ||
14 | lsl a7fa563e-b699-48e2-b27f-7cd3737e5702 ~poser 4 | ||
15 | lsl a3bb1355-bdbb-4c25-8907-437add217f14 ~poser 5 | ||
16 | lsl 3b0abc52-f892-4846-97ae-c4e7b159c644 ~poser | ||
17 | lsl 9e03bb0c-c48e-4855-8e33-91519bed560e ~pos | ||
18 | lsl 1a06486b-9e63-4a4c-ad65-7572cda834bd ~props | ||
19 | lsl c2119303-2a2d-4685-b9e6-6a07797225f4 ~run | ||
20 | |||
diff --git a/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~ball/index.omg b/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~ball/index.omg new file mode 100644 index 0000000..ea9d81b --- /dev/null +++ b/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~ball/index.omg | |||
@@ -0,0 +1 @@ | |||
lsl 0cfaeafe-ac53-4575-af89-0b79a39522d2 ~ball | |||
diff --git a/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~ball/~ball.lsl b/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~ball/~ball.lsl new file mode 100644 index 0000000..ff5cca3 --- /dev/null +++ b/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~ball/~ball.lsl | |||
@@ -0,0 +1,161 @@ | |||
1 | // MLPV2 Version 2.3 by Learjeff Innis. Based on | ||
2 | // MLP MULTI-LOVE-POSE V1.2 - Copyright (c) 2006, by Miffy Fluffy (BSD License) | ||
3 | // OpenSim port by Jez Ember | ||
4 | // Meta 7 fixes by onefang Rejected | ||
5 | |||
6 | // To make ball phantom, put "*" as the first character in the ball's description | ||
7 | // (The ball in MLP object's inventory should be non-phantom.) | ||
8 | // The rest of the description, if any, is used for the sit pie menu and floating text. | ||
9 | // To make this take effect, use STOP to unrez the balls, and then select any pose. | ||
10 | |||
11 | integer Chan; | ||
12 | integer Group; | ||
13 | integer visible = TRUE; | ||
14 | integer Adjusting; | ||
15 | key Avatar; | ||
16 | string Name; | ||
17 | integer Handle; | ||
18 | |||
19 | // 15 color support, thanks to Liz Silverstein | ||
20 | // Color is passed as a string by object chat (from menu via poser*) | ||
21 | |||
22 | list colors = [ <0.0,0.0,0.0>, // 0 = HIDE | ||
23 | <0.835,0.345,0.482>, // 1 = PINK | ||
24 | <0.353,0.518,0.827>, // 2 = BLUE | ||
25 | <0.635,0.145,0.282>, // 3 = PINK2 - Dark pink | ||
26 | <0.153,0.318,0.627>, // 4 = BLUE2 - Dark blue | ||
27 | <0.128,0.500,0.128>, // 5 = GREEN | ||
28 | <1.000,0.000,1.000>, // 6 = MAGENTA | ||
29 | <1.000,0.000,0.000>, // 7 = RED | ||
30 | <1.000,0.500,0.000>, // 8 = ORANGE | ||
31 | <1.000,1.000,1.000>, // 9 = WHITE | ||
32 | <0.0,0.0,0.0>, // 10 = BLACK | ||
33 | <1.0,1.0,0.0>, // 11 = YELLOW | ||
34 | <0.0,0.8,0.8>, // 12 = CYAN | ||
35 | <0.5,0.0,0.0>, // 13 = RED2 | ||
36 | <0.0,0.5,0.5>, // 14 = TEAL | ||
37 | <0.0,0.25,0.25>]; // 15 = GREEN2 | ||
38 | |||
39 | |||
40 | render() { | ||
41 | if (!visible || (Avatar != NULL_KEY && !Adjusting)) { | ||
42 | // hidden | ||
43 | llSetScale(<0.01,0.01,0.01>); | ||
44 | llSetAlpha(0.0, ALL_SIDES); | ||
45 | llSetText("",<1.0,1.0,1.0>,1.0); | ||
46 | } else if (Avatar != NULL_KEY && Adjusting) { | ||
47 | // sitting and adjusting | ||
48 | llSetAlpha(0.2,ALL_SIDES); | ||
49 | llSetText("Adjust",<1.0,1.0,1.0>,1.0); | ||
50 | llSetScale(<0.1,0.1,5.0>); | ||
51 | } else { | ||
52 | // shown | ||
53 | llSetAlpha(1.0, ALL_SIDES); | ||
54 | llSetScale(<0.2,0.2,0.2>); | ||
55 | if (Adjusting) { | ||
56 | llSetText("Adjust",<1.0,1.0,1.0>,1.0); | ||
57 | } else { | ||
58 | llSetText(Name,<1.0,1.0,1.0>,1.0); | ||
59 | } | ||
60 | } | ||
61 | } | ||
62 | |||
63 | show() { | ||
64 | visible = TRUE; | ||
65 | render(); | ||
66 | } | ||
67 | |||
68 | hide() { | ||
69 | visible = FALSE; | ||
70 | render(); | ||
71 | } | ||
72 | |||
73 | default { | ||
74 | on_rez(integer channel) { | ||
75 | Name = llGetObjectDesc(); | ||
76 | if (Name == "" || Name == "(No Description)") { | ||
77 | Name = "LOVE"; | ||
78 | } else { | ||
79 | if (llSubStringIndex(Name, "*") == 0) { | ||
80 | llSetPrimitiveParams([PRIM_PHANTOM, TRUE]); | ||
81 | Name = llGetSubString(Name, 1, -1); | ||
82 | } | ||
83 | if (Name == "none") { | ||
84 | Name = ""; | ||
85 | } | ||
86 | } | ||
87 | llSitTarget(<0.0,0.0,-0.1>,ZERO_ROTATION); | ||
88 | if (Name != "") { | ||
89 | llSetSitText(Name); | ||
90 | } | ||
91 | Avatar = NULL_KEY; | ||
92 | Chan = channel; | ||
93 | Group = 0; | ||
94 | |||
95 | if (Chan != 0) { | ||
96 | // register listen and start timer, unless ball was dragged from inv | ||
97 | llListenRemove(Handle); | ||
98 | Handle = llListen(Chan,"",NULL_KEY,""); | ||
99 | llSetTimerEvent(600.0); | ||
100 | } | ||
101 | } | ||
102 | |||
103 | changed(integer change) { | ||
104 | if (change != CHANGED_LINK) return; | ||
105 | Avatar = llAvatarOnSitTarget(); | ||
106 | if (Group) { | ||
107 | if (Avatar != NULL_KEY && !llSameGroup(Avatar)) { | ||
108 | llUnSit(Avatar); | ||
109 | llWhisper(0,"no permission to use poseball"); | ||
110 | return; | ||
111 | } | ||
112 | } | ||
113 | llSay(Chan+8,(string)Avatar); //requests perm, sets animation | ||
114 | render(); | ||
115 | // if (visible & Avatar == NULL_KEY) show(); else hide(); | ||
116 | } | ||
117 | |||
118 | listen(integer channel, string name, key object, string str) { | ||
119 | integer ix; | ||
120 | ix = llSubStringIndex(str,">"); | ||
121 | if (ix != -1) { | ||
122 | llSetRot((rotation)llGetSubString(str,ix+1,-1)); | ||
123 | llSetPos((vector)llGetSubString(str,0,ix)); | ||
124 | } else if (str == "0") { //HIDE | ||
125 | hide(); | ||
126 | } else if (str == "SHOW") { //SHOW | ||
127 | show(); | ||
128 | } else if (str == "ADJUST|1") { | ||
129 | Adjusting = TRUE; | ||
130 | render(); | ||
131 | } else if (str == "ADJUST|0") { | ||
132 | Adjusting = FALSE; | ||
133 | render(); | ||
134 | } else if (str == "SAVE") { | ||
135 | llSay(Chan+16,(string)llGetPos()+(string)llGetRot()); | ||
136 | } else if (str == "GROUP") { | ||
137 | Group = 1; | ||
138 | } else if (str == "ALL") { | ||
139 | Group = 0; | ||
140 | } else if (str == "DIE") { | ||
141 | llSay(Chan+8, (string)NULL_KEY); //msg to poser (don't reanimate after STOP) | ||
142 | llDie(); | ||
143 | } else if (str == "LIVE") { | ||
144 | llSetTimerEvent(600.0); | ||
145 | } else { | ||
146 | list ldata = llParseString2List(str, ["|"], []); | ||
147 | integer colorIx = (integer) llList2String(ldata,0); | ||
148 | string ballIx = llList2String(ldata,1); | ||
149 | Adjusting = (integer) llList2String(ldata,2); | ||
150 | if ((colorIx > 0) && (colorIx < 16)) { // this must be a color setting | ||
151 | llSetColor(llList2Vector(colors, colorIx),ALL_SIDES); //pull the color out of the list | ||
152 | render(); | ||
153 | llSetObjectName("~ball" + ballIx); | ||
154 | } | ||
155 | } | ||
156 | } | ||
157 | |||
158 | timer() { //not heard "LIVE" from menu for a while: suicide | ||
159 | llDie(); | ||
160 | } | ||
161 | } | ||
diff --git a/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~memory.lsl b/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~memory.lsl new file mode 100644 index 0000000..c72b6e2 --- /dev/null +++ b/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~memory.lsl | |||
@@ -0,0 +1,378 @@ | |||
1 | //MPLV2 Version 2.2 by Learjeff Innis, based on | ||
2 | //MLP MULTI-LOVE-POSE V1.2 - Copyright (c) 2006, by Miffy Fluffy (BSD License) | ||
3 | // OpenSim port by Jez Ember | ||
4 | // Meta 7 fixes by onefang Rejected | ||
5 | |||
6 | // v2.2 - rotate all poses, cleaner dump | ||
7 | |||
8 | integer Checking = FALSE; // whether doing consistency check | ||
9 | |||
10 | integer line; | ||
11 | integer PosCount; | ||
12 | list Poses; // list of pose names | ||
13 | |||
14 | // indexed by same index as Poses, entry contains text string of pos/rot pairs, one for each ball in pose | ||
15 | |||
16 | // list Positions; | ||
17 | |||
18 | list Positions0; | ||
19 | list Positions1; | ||
20 | list Positions2; | ||
21 | list Positions3; | ||
22 | |||
23 | vector Pos1; | ||
24 | vector Pos2; | ||
25 | vector Pos3; | ||
26 | vector Pos4; | ||
27 | vector Pos5; | ||
28 | vector Pos6; | ||
29 | vector Rot1; | ||
30 | vector Rot2; | ||
31 | vector Rot3; | ||
32 | vector Rot4; | ||
33 | vector Rot5; | ||
34 | vector Rot6; | ||
35 | integer Ballcount; | ||
36 | |||
37 | // Replacement for llListFindList which is currently broken in OSLSL | ||
38 | integer myListFind(list a, string b) { | ||
39 | integer x; | ||
40 | integer l=llGetListLength(a); | ||
41 | |||
42 | for(x=0; x<l; x++) { | ||
43 | if(llList2String(a,x) == b) { | ||
44 | return x; | ||
45 | } | ||
46 | } | ||
47 | |||
48 | return -1; | ||
49 | } | ||
50 | |||
51 | announce() | ||
52 | { | ||
53 | llOwnerSay((string)PosCount | ||
54 | + " positions stored (" | ||
55 | + llGetScriptName() | ||
56 | + ": " | ||
57 | + (string)llGetFreeMemory() | ||
58 | + " bytes free)"); | ||
59 | } | ||
60 | |||
61 | getPosePos(string pdata) { | ||
62 | list plist = llParseString2List(pdata,[" "],[]); | ||
63 | |||
64 | Ballcount = llGetListLength(plist) / 2; | ||
65 | |||
66 | Pos1 = (vector)llList2String(plist, 0); | ||
67 | Rot1 = (vector)llList2String(plist, 1); | ||
68 | Pos2 = (vector)llList2String(plist, 2); | ||
69 | Rot2 = (vector)llList2String(plist, 3); | ||
70 | Pos3 = (vector)llList2String(plist, 4); | ||
71 | Rot3 = (vector)llList2String(plist, 5); | ||
72 | Pos4 = (vector)llList2String(plist, 6); | ||
73 | Rot4 = (vector)llList2String(plist, 7); | ||
74 | Pos5 = (vector)llList2String(plist, 8); | ||
75 | Rot5 = (vector)llList2String(plist, 8); | ||
76 | Pos6 = (vector)llList2String(plist, 10); | ||
77 | Rot6 = (vector)llList2String(plist, 11); | ||
78 | } | ||
79 | |||
80 | |||
81 | string adjust(integer doOffset, vector pos, vector erot, vector amt) { | ||
82 | if (doOffset) { | ||
83 | pos += amt/100.; | ||
84 | return (vround(pos) + " " + vround(erot)); | ||
85 | } | ||
86 | |||
87 | rotation amount = llEuler2Rot(amt * DEG_TO_RAD); | ||
88 | erot *= DEG_TO_RAD; | ||
89 | |||
90 | rotation oldrot = llEuler2Rot(erot); | ||
91 | rotation newrot = oldrot / amount; | ||
92 | |||
93 | erot = llRot2Euler(newrot) * RAD_TO_DEG; | ||
94 | pos = pos / amount; | ||
95 | return(vround(pos) + " " + vround(erot)); | ||
96 | } | ||
97 | |||
98 | adjust_all(integer doOffset, vector amt) { | ||
99 | integer ix; | ||
100 | integer bx; | ||
101 | string data; | ||
102 | for (ix = 0; ix < PosCount; ++ix) { | ||
103 | data = get_pose_by_index(ix); | ||
104 | getPosePos(data); | ||
105 | |||
106 | list parms = [ Pos1, Rot1, Pos2, Rot2, Pos3, Rot3, Pos4, Rot4, Pos5, Rot5, Pos6, Rot6 ]; | ||
107 | |||
108 | data = adjust(doOffset, Pos1, Rot1, amt); | ||
109 | integer ballix = 1; | ||
110 | while (ballix < Ballcount) { | ||
111 | string stuff = adjust(doOffset, llList2Vector(parms, 2*ballix), llList2Vector(parms, 2*ballix+1), amt); | ||
112 | data += " " + stuff; | ||
113 | ++ballix; | ||
114 | } | ||
115 | store_pose(data, ix); | ||
116 | } | ||
117 | } | ||
118 | |||
119 | |||
120 | string get_pose_data(string name) { | ||
121 | integer ix = myListFind(Poses, name); | ||
122 | |||
123 | // if not found, use default positions | ||
124 | if (ix == -1) { | ||
125 | ix = 0; | ||
126 | } | ||
127 | |||
128 | return (get_pose_by_index(ix)); | ||
129 | } | ||
130 | |||
131 | |||
132 | string get_pose_by_index(integer ix) { | ||
133 | if ((ix & 3) == 0) { | ||
134 | return llList2String(Positions0, ix>>2); | ||
135 | } else if ((ix & 3) == 1) { | ||
136 | return llList2String(Positions1, ix>>2); | ||
137 | } else if ((ix & 3) == 2) { | ||
138 | return llList2String(Positions2, ix>>2); | ||
139 | } | ||
140 | return llList2String(Positions3, ix>>2); | ||
141 | } | ||
142 | |||
143 | store_pose(string data, integer ix) { | ||
144 | if ((ix & 3) == 0) { | ||
145 | Positions0 = llListReplaceList(Positions0,[ data ],ix>>2,ix>>2); | ||
146 | } else if ((ix & 3) == 1) { | ||
147 | Positions1 = llListReplaceList(Positions1,[ data ],ix>>2,ix>>2); | ||
148 | } else if ((ix & 3) == 2) { | ||
149 | Positions2 = llListReplaceList(Positions2,[ data ],ix>>2,ix>>2); | ||
150 | } else if ((ix & 3) == 3) { | ||
151 | Positions3 = llListReplaceList(Positions3,[ data ],ix>>2,ix>>2); | ||
152 | } | ||
153 | } | ||
154 | |||
155 | |||
156 | save_pose(string name, string data) { | ||
157 | integer ix = myListFind(Poses, name); | ||
158 | if (ix == -1) { | ||
159 | add_pose(name, data); | ||
160 | } else { | ||
161 | store_pose(data, ix); | ||
162 | } | ||
163 | } | ||
164 | |||
165 | add_pose(string name, string data) { | ||
166 | integer ix = myListFind(Poses, name); | ||
167 | if (ix != -1) { | ||
168 | llOwnerSay("===> WARNING: Multiple .POSITIONS* entries for '" + name + "'"); | ||
169 | } else { | ||
170 | Poses += (list) name; | ||
171 | ix = ++PosCount; | ||
172 | } | ||
173 | store_pose(data, ix-1); | ||
174 | } | ||
175 | |||
176 | check_pose(string name) { | ||
177 | integer ix; | ||
178 | |||
179 | // if this is the last pose, report results | ||
180 | if (name == "CHECK2") { | ||
181 | string nameA; | ||
182 | for (ix = 0; ix < llGetListLength(Poses); ++ix) { | ||
183 | nameA = llList2String(Poses, ix); | ||
184 | if (get_pose_data(nameA) != "") { | ||
185 | if (nameA != "default" && nameA != "stand") { | ||
186 | llOwnerSay("No .MENUITEMS* entry for '" + nameA + "'."); | ||
187 | } | ||
188 | } | ||
189 | } | ||
190 | llOwnerSay("Checks complete, resetting."); | ||
191 | llResetScript(); | ||
192 | } | ||
193 | |||
194 | ix = myListFind(Poses, name); | ||
195 | if (ix == -1) { | ||
196 | llOwnerSay("No .POSITIONS* entry for '" + name + "'."); | ||
197 | return; | ||
198 | } | ||
199 | save_pose(name, ""); | ||
200 | } | ||
201 | |||
202 | |||
203 | string vround(vector vec) { | ||
204 | return ("<"+round(vec.x, 3)+","+round(vec.y, 3)+","+round(vec.z, 3)+">"); | ||
205 | } | ||
206 | |||
207 | string round(float number, integer places) { | ||
208 | float shifted; | ||
209 | integer rounded; | ||
210 | string s; | ||
211 | shifted = number * llPow(10.0,(float)places); | ||
212 | rounded = llRound(shifted); | ||
213 | s = (string)((float)rounded / llPow(10.0,(float)places)); | ||
214 | rounded = llSubStringIndex(s, "."); | ||
215 | if (-1 != rounded) | ||
216 | s = llGetSubString(s,0,llSubStringIndex(s, ".")+places); | ||
217 | else | ||
218 | { | ||
219 | s += ".00000000"; | ||
220 | s = llGetSubString(s,0,llSubStringIndex(s, ".")+places); | ||
221 | } | ||
222 | return s; | ||
223 | } | ||
224 | |||
225 | dashes() { | ||
226 | llOwnerSay("_______________________________________________________________________________"); | ||
227 | llOwnerSay(""); | ||
228 | } | ||
229 | |||
230 | |||
231 | // Globals for reading card config | ||
232 | integer ConfigLineIndex; | ||
233 | list ConfigCards; // list of names of config cards | ||
234 | string ConfigCardName; // name of card being read | ||
235 | integer ConfigCardIndex; // index of next card to read | ||
236 | key ConfigQueryId; | ||
237 | |||
238 | integer next_card() | ||
239 | { | ||
240 | if (ConfigCardIndex >= llGetListLength(ConfigCards)) { | ||
241 | ConfigCards = []; | ||
242 | return (FALSE); | ||
243 | } | ||
244 | |||
245 | ConfigLineIndex = 0; | ||
246 | ConfigCardName = llList2String(ConfigCards, ConfigCardIndex); | ||
247 | ConfigCardIndex++; | ||
248 | ConfigQueryId = llGetNotecardLine(ConfigCardName, ConfigLineIndex); | ||
249 | llOwnerSay("Reading " + ConfigCardName); | ||
250 | return (TRUE); | ||
251 | } | ||
252 | |||
253 | |||
254 | default { | ||
255 | state_entry() { | ||
256 | string item; | ||
257 | ConfigCards = []; | ||
258 | integer n = llGetInventoryNumber(INVENTORY_NOTECARD); | ||
259 | while (n-- > 0) { | ||
260 | item = llGetInventoryName(INVENTORY_NOTECARD, n); | ||
261 | if (llSubStringIndex(item, ".POSITIONS") != -1) { | ||
262 | ConfigCards += (list) item; | ||
263 | } | ||
264 | } | ||
265 | |||
266 | ConfigCardIndex = 0; | ||
267 | ConfigCards = llListSort(ConfigCards, 1, TRUE); | ||
268 | next_card(); | ||
269 | } | ||
270 | |||
271 | dataserver(key query_id, string data) { | ||
272 | if (query_id != ConfigQueryId) { | ||
273 | return; | ||
274 | } | ||
275 | if (data == EOF) { | ||
276 | if (next_card()) { | ||
277 | return; | ||
278 | } | ||
279 | state on; | ||
280 | } | ||
281 | if (llGetSubString(data,0,0) != "/") { // skip comments | ||
282 | integer ix = llSubStringIndex(data, "{"); //split name from positions, remove junk | ||
283 | integer jx = llSubStringIndex(data, "} <"); | ||
284 | if (ix != -1 && jx != -1) { | ||
285 | add_pose(llGetSubString(data, ix+1, jx-1), llGetSubString(data, jx+2, -1)); | ||
286 | } | ||
287 | } | ||
288 | ++ConfigLineIndex; | ||
289 | ConfigQueryId = llGetNotecardLine(ConfigCardName, ConfigLineIndex); //read next line of positions notecard | ||
290 | } | ||
291 | |||
292 | state_exit() { | ||
293 | if (PosCount < 1) { | ||
294 | add_pose("stand", "<-0.7,0.0,0.9> <0.0,0.0,0.0> <0.7,0.0,0.9> <0.0,0.0,-180.0>"); | ||
295 | } | ||
296 | if (PosCount < 2) { | ||
297 | add_pose("default", "<-0.7,0.0,0.7> <0.0,0.0,0.0> <0.7,0.0,0.7> <0.0,0.0,-180.0>"); | ||
298 | } | ||
299 | |||
300 | // do one save to indicate actual amount of available memory | ||
301 | string position = llList2String(Positions1, 0); | ||
302 | Positions1 = llListReplaceList(Positions1, [position],0,0); | ||
303 | |||
304 | if (llGetInventoryType("~props") == INVENTORY_SCRIPT) { | ||
305 | llSetScriptState("~props", TRUE); | ||
306 | llResetOtherScript("~props"); | ||
307 | llSleep(1.0); // give props a chance to run -- doesn't really matter if not enough | ||
308 | } | ||
309 | } | ||
310 | } | ||
311 | |||
312 | |||
313 | state on { | ||
314 | state_entry() { | ||
315 | llMessageLinked(LINK_THIS, 2, "OK", (key)""); //msg to menu, in case it's waiting for loading | ||
316 | announce(); | ||
317 | } | ||
318 | |||
319 | link_message(integer from, integer num, string str, key dkey) { | ||
320 | if (str == "PRIMTOUCH" || num < 0) { | ||
321 | return; | ||
322 | } | ||
323 | |||
324 | if (num == 0 && str == "POSEB") { | ||
325 | string name = (string)dkey; | ||
326 | if (name == "CHECK1") { | ||
327 | Checking = TRUE; | ||
328 | } else if (Checking) { | ||
329 | check_pose((string)dkey); | ||
330 | } else { | ||
331 | llMessageLinked(LINK_THIS, 0, "POSEPOS", (key)get_pose_data((string)dkey)); // to ~pos | ||
332 | } | ||
333 | return; | ||
334 | } | ||
335 | |||
336 | if (num != 1) { | ||
337 | return; | ||
338 | } | ||
339 | |||
340 | if (str == "OK?") { //question from menu, before loading menu | ||
341 | llMessageLinked(from, 2, "OK", (key)""); //answer to menu | ||
342 | } else if (str == "DUMP") { | ||
343 | dashes(); | ||
344 | llOwnerSay("Copy to .POSITIONS; delete any other *.POSITIONS* cards"); | ||
345 | dashes(); | ||
346 | string name = llGetObjectName(); | ||
347 | llSetObjectName(""); | ||
348 | |||
349 | integer ix; | ||
350 | for (ix = 0; ix < PosCount; ++ix) { | ||
351 | string nameA = llList2String(Poses, ix); | ||
352 | llOwnerSay("{" + nameA + "} " + get_pose_data(nameA)); | ||
353 | } | ||
354 | |||
355 | llSetObjectName(name); | ||
356 | dashes(); | ||
357 | } else if (llSubStringIndex(str, "REORIENT=") == 0) { | ||
358 | // Reorient command (LINKMENU command from .MENUITEMS file) | ||
359 | // str format: REORIENT=OFF=<x,y,z> or REORIENT=ROT=<x,y,z> (in degrees) | ||
360 | list parms = llParseString2List(str, ["="], []); | ||
361 | vector amount = (vector)llList2String(parms, 2); | ||
362 | llWhisper(0, "Adjusting Poses, please wait"); | ||
363 | |||
364 | if (llList2String(parms, 1) == "OFF") { | ||
365 | adjust_all(TRUE, amount); | ||
366 | } else { | ||
367 | adjust_all(FALSE, amount); | ||
368 | } | ||
369 | llMessageLinked(LINK_THIS, 0, "AGAIN", (key)""); | ||
370 | llWhisper(0, "Pose adjustment complete"); | ||
371 | } else { | ||
372 | if (llGetSubString((string)dkey, 0, 0) == "<") { //SAVE | ||
373 | save_pose(str, (string)dkey); | ||
374 | announce(); | ||
375 | } | ||
376 | } | ||
377 | } | ||
378 | } | ||
diff --git a/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~menu.lsl b/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~menu.lsl new file mode 100644 index 0000000..ea19396 --- /dev/null +++ b/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~menu.lsl | |||
@@ -0,0 +1,529 @@ | |||
1 | // MLPV2 Version 2.3, by Learjeff Innis, based on | ||
2 | // MLP MULTI-LOVE-POSE V1.2 - Copyright (c) 2006, by Miffy Fluffy (BSD License) | ||
3 | // 15-color balls by Lizz Silverstar | ||
4 | // OpenSim port by Jez Ember | ||
5 | // Meta 7 fixes by onefang Rejected | ||
6 | |||
7 | // 2.3: sequences | ||
8 | // 6 avs | ||
9 | // Adjusting state | ||
10 | |||
11 | integer MAX_BALLS = 6; | ||
12 | |||
13 | string Version = "MLPV2.5"; | ||
14 | |||
15 | integer b; | ||
16 | integer b0; | ||
17 | integer ballusers; | ||
18 | list BallColors; | ||
19 | integer ch; | ||
20 | integer chat = 1; | ||
21 | integer group; | ||
22 | integer i; | ||
23 | integer menu; | ||
24 | integer menuusers; | ||
25 | integer redo = 1; | ||
26 | integer swap; | ||
27 | integer visible; | ||
28 | integer BallCount; | ||
29 | integer SaneMenuOrder; | ||
30 | integer ReloadOnRez; | ||
31 | |||
32 | integer Adjusting; | ||
33 | string LastPose; | ||
34 | |||
35 | integer BallsNeeded; | ||
36 | |||
37 | float alpha; | ||
38 | string cmd; | ||
39 | string pose; | ||
40 | string Posemsg; // for 'AGAIN' | ||
41 | key owner; | ||
42 | key user; | ||
43 | key user0; | ||
44 | list buttons; | ||
45 | list buttonindex; | ||
46 | list commands; | ||
47 | list menus; | ||
48 | list balls; | ||
49 | list users; | ||
50 | |||
51 | list SoundNames; | ||
52 | list Sounds; | ||
53 | list LMButtons; | ||
54 | list LMParms; | ||
55 | list MenuStack = [0]; // indices to previous menus, for "BACK" command | ||
56 | |||
57 | integer MenuPage; // which page of current menu we're on, 0 for first | ||
58 | |||
59 | // Replacement for llListFindList which is currently broken in OSLSL | ||
60 | integer myListFind(list a, string b) { | ||
61 | integer x; | ||
62 | integer l=llGetListLength(a); | ||
63 | |||
64 | for(x=0; x<l; x++) { | ||
65 | if(llList2String(a,x) == b) { | ||
66 | return x; | ||
67 | } | ||
68 | } | ||
69 | |||
70 | return -1; | ||
71 | } | ||
72 | |||
73 | stop() { | ||
74 | sendStand(); //msg to pos/pose | ||
75 | llMessageLinked(LINK_THIS, 1, "STOP", (key)""); | ||
76 | llSleep(0.2); | ||
77 | killBalls(); | ||
78 | swap = 0; | ||
79 | Adjusting = FALSE; | ||
80 | } | ||
81 | |||
82 | |||
83 | check_poses() { | ||
84 | llOwnerSay("Checking configs"); | ||
85 | llMessageLinked(LINK_THIS,0,"POSEB", (key)"CHECK1"); //msg to memory | ||
86 | integer ix; | ||
87 | string name; | ||
88 | for (ix = 0; ix < llGetListLength(buttons); ++ix) { | ||
89 | name = llList2String(buttons, ix); | ||
90 | if (((integer)llList2String(commands, ix)) != 0) { | ||
91 | llMessageLinked(LINK_THIS,0,"POSEB", (key)name); //msg to memory | ||
92 | } | ||
93 | } | ||
94 | llMessageLinked(LINK_THIS,0,"POSEB", (key)"CHECK2"); //msg to memory | ||
95 | } | ||
96 | |||
97 | // Return a channel number that's based on the prim's key -- unique per object | ||
98 | integer channel() { | ||
99 | return (integer)("0x"+llGetSubString((string)llGetKey(),-4,-1)); | ||
100 | } | ||
101 | |||
102 | |||
103 | // setup for a pose based on menu characteristics | ||
104 | setup_pose() { | ||
105 | if (BallsNeeded) { // if submenu includes balls: | ||
106 | if (BallCount != BallsNeeded) { | ||
107 | rezBalls(); // if not enough balls present: create balls | ||
108 | llSleep(0.5); | ||
109 | } | ||
110 | integer ix; | ||
111 | for (ix = 0; ix < BallsNeeded; ++ix) { | ||
112 | llSay(ch + ix, llList2String(BallColors, ix) // to ball: color, ballnum, adjusting | ||
113 | + "|" + (string) ix | ||
114 | + "|" + (string) Adjusting); | ||
115 | } | ||
116 | if (ballusers) setBalls("GROUP"); //if group access only | ||
117 | } | ||
118 | } | ||
119 | |||
120 | |||
121 | unauth(string button, string who) { | ||
122 | llDialog(user0, "\n" + button + " button allowed only for " + who, ["OK"], -1); | ||
123 | } | ||
124 | |||
125 | continMenu(string str) { | ||
126 | llDialog(user0, "\n"+str+llKey2Name(user)+" is using the menu, continue?", ["Yes","Cancel"], ch - 1); | ||
127 | } | ||
128 | |||
129 | mainMenu() { | ||
130 | MenuPage = 0; | ||
131 | menu = 0; | ||
132 | doMenu(FALSE); | ||
133 | } | ||
134 | |||
135 | //menu partly based on Menu Engine by Zonax Delorean (BSD License) | ||
136 | //llDialog(user, menuname, buttons(from index to nextindex-1), channel) | ||
137 | doMenu(integer inhibit_showing) { | ||
138 | integer colors = llList2Integer(balls,menu); | ||
139 | integer ix; | ||
140 | integer mask = 0xf; | ||
141 | integer shift = 0; | ||
142 | BallsNeeded = 0; | ||
143 | BallColors = []; | ||
144 | |||
145 | for (ix = 0; ix < MAX_BALLS; ++ix) { | ||
146 | integer bc = (colors & mask) >> ix*4; | ||
147 | BallColors += (list)bc; | ||
148 | if (bc) { | ||
149 | BallsNeeded += 1; | ||
150 | } | ||
151 | mask = mask << 4; | ||
152 | } | ||
153 | |||
154 | if (inhibit_showing) { | ||
155 | return; | ||
156 | } | ||
157 | |||
158 | b0 = llList2Integer(buttonindex, menu); //position of first button for this (sub)menu | ||
159 | b = llList2Integer(buttonindex, menu+1); //position of first button for next (sub)menu | ||
160 | |||
161 | b0 += MenuPage * 12; | ||
162 | if (b - b0 > 12) { | ||
163 | b = b0 + 12; | ||
164 | } | ||
165 | |||
166 | list buttons1; | ||
167 | buttons1 = llList2List(buttons, b0, b - 1); | ||
168 | if (SaneMenuOrder) { | ||
169 | buttons1 = | ||
170 | llList2List(buttons1, -3, -1) | ||
171 | + llList2List(buttons1, -6, -4) | ||
172 | + llList2List(buttons1, -9, -7) | ||
173 | + llList2List(buttons1, -12, -10); | ||
174 | } | ||
175 | llDialog(user, Version + "\n\n" + llList2String(menus,menu), buttons1, ch - 1); | ||
176 | llResetTime(); | ||
177 | } | ||
178 | |||
179 | say(string str) { | ||
180 | if (menuusers) llWhisper(0,str); | ||
181 | else llOwnerSay(str); | ||
182 | } | ||
183 | |||
184 | killBalls() { | ||
185 | integer ix; | ||
186 | for (ix = 0; ix < MAX_BALLS; ++ix) { | ||
187 | llSay(ch + ix, "DIE"); //msg to balls | ||
188 | } | ||
189 | BallCount = 0; | ||
190 | llSetTimerEvent(0.0); | ||
191 | } | ||
192 | |||
193 | setBalls(string cmd) { | ||
194 | integer ix; | ||
195 | for (ix = 0; ix < BallCount; ++ix) { | ||
196 | llSay(ch + ix, cmd); //msg to balls | ||
197 | } | ||
198 | } | ||
199 | |||
200 | |||
201 | rezBalls() { | ||
202 | integer current = BallCount; | ||
203 | |||
204 | if (BallsNeeded == BallCount) return; | ||
205 | |||
206 | if (BallCount == 0) { | ||
207 | killBalls(); // for reinitialization, if old balls are around | ||
208 | } | ||
209 | |||
210 | while (BallCount > BallsNeeded) { | ||
211 | --BallCount; | ||
212 | llSay(ch + BallCount, "DIE"); | ||
213 | } | ||
214 | |||
215 | while (BallCount < BallsNeeded) { | ||
216 | llRezObject("~ball",llGetPos(),ZERO_VECTOR,ZERO_ROTATION,ch+BallCount); | ||
217 | ++BallCount; | ||
218 | } | ||
219 | |||
220 | // Only do this if there were no balls | ||
221 | if (! current) { | ||
222 | llMessageLinked(LINK_THIS,0,"REPOS",(key)""); //msg to pos | ||
223 | } | ||
224 | |||
225 | llSetTimerEvent(30.0); | ||
226 | } | ||
227 | |||
228 | |||
229 | |||
230 | sendStand() { | ||
231 | llMessageLinked(LINK_THIS,0,"POSE","0,"+(string)BallCount); //msg to pos/pose | ||
232 | llMessageLinked(LINK_THIS,0,"POSEB", "stand"); | ||
233 | } | ||
234 | |||
235 | touched(integer same_group) { | ||
236 | if (user0 == owner || (menuusers == 1 && same_group) || menuusers == 2) { //0=owner 1=group 2=all | ||
237 | if (user0 != user) { | ||
238 | if (llGetTime() < 60.0 && user != (key)"") { | ||
239 | continMenu(""); | ||
240 | return; | ||
241 | } | ||
242 | user = user0; | ||
243 | group = same_group; | ||
244 | } | ||
245 | mainMenu(); | ||
246 | } | ||
247 | } | ||
248 | |||
249 | |||
250 | // return TRUE if caller should do menu | ||
251 | integer handle_cmd(string button, integer sequenced) { | ||
252 | b = myListFind(buttons, button); //find position of cmd | ||
253 | string cmd = llList2String(commands,b); //get command | ||
254 | |||
255 | if (cmd == "TOMENU") { | ||
256 | integer newmenu = myListFind(menus, button); //find submenu | ||
257 | if (newmenu == -1) return FALSE; | ||
258 | if (sequenced) { | ||
259 | integer oldmenu = menu; | ||
260 | menu = newmenu; | ||
261 | doMenu(TRUE); | ||
262 | setup_pose(); | ||
263 | menu = oldmenu; | ||
264 | return FALSE; | ||
265 | } | ||
266 | i = llList2Integer(users, newmenu); | ||
267 | if (user == owner || (i == 1 && group) || i == 2) { //0=owner 1=group 2=all | ||
268 | MenuStack = (list)menu + MenuStack; | ||
269 | MenuPage = 0; | ||
270 | menu = newmenu; | ||
271 | doMenu(sequenced); | ||
272 | return FALSE; | ||
273 | } | ||
274 | if (i == 1) unauth(button, "group"); | ||
275 | else unauth(button, "owner"); | ||
276 | return FALSE; | ||
277 | } else if (cmd == "BACK") { | ||
278 | if (MenuPage) { | ||
279 | --MenuPage; | ||
280 | doMenu(sequenced); | ||
281 | return FALSE; | ||
282 | } | ||
283 | menu = llList2Integer(MenuStack,0); | ||
284 | MenuStack = llList2List(MenuStack,1,-1); | ||
285 | doMenu(sequenced); | ||
286 | return FALSE; | ||
287 | } else if (cmd == "MORE") { | ||
288 | ++MenuPage; | ||
289 | doMenu(sequenced); | ||
290 | return FALSE; | ||
291 | } else if (cmd == "CHECK") { | ||
292 | check_poses(); | ||
293 | } else if ((integer)cmd > 0) { //POSE | ||
294 | if (Adjusting && button != pose) { | ||
295 | llMessageLinked(LINK_THIS,0,"SAVE",pose); //msg to pos/pose | ||
296 | llSleep(5.); | ||
297 | } | ||
298 | setup_pose(); | ||
299 | Posemsg = cmd + "," + (string) BallCount; | ||
300 | llMessageLinked(LINK_THIS,0,"POSE", Posemsg); //msg to pose | ||
301 | llMessageLinked(LINK_THIS,0,"POSEB", (key)button); //msg to memory | ||
302 | if (chat) say(button); | ||
303 | pose = button; | ||
304 | } else if (cmd == "SWAP") { | ||
305 | swap += 1; | ||
306 | llMessageLinked(LINK_THIS,0,"SWAP",(key)((string)swap)); //msg to pos/pose | ||
307 | } else if (cmd == "STAND") { | ||
308 | sendStand(); //msg to pos/pose | ||
309 | if (chat) say(button); | ||
310 | pose = "stand"; | ||
311 | } else if (cmd == "STOP") { | ||
312 | if (chat) say(button); | ||
313 | stop(); | ||
314 | return FALSE; | ||
315 | } else if (cmd == "ADJUST") { | ||
316 | Adjusting = ! Adjusting; | ||
317 | setBalls("ADJUST|" + (string)Adjusting); | ||
318 | } else if (cmd == "HIDE") { | ||
319 | setBalls("0"); | ||
320 | } else if (cmd == "SHOW") { | ||
321 | setBalls("SHOW"); | ||
322 | } else if (cmd == "DUMP") { | ||
323 | llMessageLinked(LINK_THIS,1,"DUMP",(key)""); | ||
324 | } else if (cmd == "INVISIBLE") { | ||
325 | visible = !visible; | ||
326 | llSetAlpha((float)visible*alpha, ALL_SIDES); | ||
327 | } else if (cmd == "REDO") { | ||
328 | redo = !redo; | ||
329 | if (redo) say(button+" ON"); else say(button+" OFF"); | ||
330 | } else if (cmd == "CHAT") { | ||
331 | chat = !chat; | ||
332 | if (chat) say(button+" ON"); else say(button+" OFF"); | ||
333 | } else if (cmd == "BALLUSERS") { | ||
334 | ballusers = !ballusers; | ||
335 | if (ballusers) { | ||
336 | llOwnerSay(button+" GROUP"); | ||
337 | setBalls("GROUP"); | ||
338 | } else { | ||
339 | llOwnerSay(button+" ALL"); | ||
340 | setBalls("ALL"); | ||
341 | } | ||
342 | } else if (cmd == "MENUUSERS") { | ||
343 | if (user == owner) { | ||
344 | if (!menuusers) { | ||
345 | menuusers = 1; | ||
346 | llOwnerSay(button+" GROUP"); | ||
347 | } else if (menuusers == 1) { | ||
348 | menuusers = 2; | ||
349 | llOwnerSay(button+" ALL"); | ||
350 | } else if (menuusers == 2) { | ||
351 | menuusers = 0; | ||
352 | llOwnerSay(button+" OWNER"); | ||
353 | } | ||
354 | } else unauth(button, "owner"); | ||
355 | } else if (cmd == "RESET" || cmd == "RELOAD" || cmd == "RESTART") { | ||
356 | stop(); | ||
357 | if (chat) say(button); | ||
358 | if (cmd == "RESET") { | ||
359 | llResetScript(); | ||
360 | } else { | ||
361 | llResetOtherScript("~memory"); | ||
362 | if (cmd == "RESTART") { | ||
363 | llResetScript(); | ||
364 | } | ||
365 | } | ||
366 | } else if (cmd == "OFF") { | ||
367 | sendStand(); //msg to pos/pose | ||
368 | stop(); | ||
369 | if (user == owner) { | ||
370 | llOwnerSay(button); | ||
371 | llResetOtherScript("~run"); | ||
372 | llResetScript(); | ||
373 | } | ||
374 | unauth(button, "owner"); | ||
375 | return FALSE; | ||
376 | } else if (llGetSubString(cmd, 0, 0) == "Z" || (cmd == "SAVE")) { //SAVE or Z-adjust | ||
377 | llSay(0,"Z"); | ||
378 | llMessageLinked(LINK_THIS,0,cmd,pose); //msg to pos/pose | ||
379 | doMenu(sequenced); | ||
380 | return FALSE; | ||
381 | } else if (cmd == "LINKMSG") { | ||
382 | // menu button to send LM to a non-MLPV2 script | ||
383 | integer ix = myListFind(LMButtons, button); | ||
384 | if (ix != -1) { | ||
385 | list lmparms = llCSV2List(llList2String(LMParms, ix)); | ||
386 | llMessageLinked( | ||
387 | llList2Integer(lmparms, 1), // destination link# | ||
388 | llList2Integer(lmparms, 2), // 'num' arg | ||
389 | llList2String(lmparms, 3), // 'str' arg | ||
390 | user0); // key arg | ||
391 | if (llList2Integer(lmparms,0)) { // inhibit remenu? | ||
392 | return FALSE; // yes, bug out | ||
393 | } | ||
394 | } | ||
395 | } else if (cmd == "SOUND") { | ||
396 | integer ix = myListFind(SoundNames, button); | ||
397 | if (ix >= 0) { | ||
398 | llPlaySound(llList2String(Sounds, ix), 1.); | ||
399 | } | ||
400 | } | ||
401 | return TRUE; | ||
402 | } | ||
403 | |||
404 | default { | ||
405 | state_entry() { | ||
406 | ch = channel(); | ||
407 | killBalls(); | ||
408 | llSleep(2.0); // give ~run a chance to shut us down | ||
409 | llResetOtherScript("~menucfg"); | ||
410 | llResetOtherScript("~pos"); | ||
411 | llResetOtherScript("~pose"); | ||
412 | llResetOtherScript("~poser"); | ||
413 | llResetOtherScript("~poser 1"); | ||
414 | llResetOtherScript("~poser 2"); | ||
415 | llResetOtherScript("~poser 3"); | ||
416 | llResetOtherScript("~poser 4"); | ||
417 | llResetOtherScript("~poser 5"); | ||
418 | alpha = llGetAlpha(0); //store object transparancy (alpha) | ||
419 | if (alpha < 0.1) alpha = 0.5; else visible = 1; //if invisible store a visible alpha | ||
420 | } | ||
421 | |||
422 | link_message(integer from, integer num, string str, key id) { | ||
423 | if (from != llGetLinkNumber()) { return; } | ||
424 | if (num >= 0) { return;} | ||
425 | |||
426 | // LMs from ~memory, passing configuration | ||
427 | if (num == -1) { | ||
428 | buttons = llCSV2List(str); | ||
429 | } else if (num == -2) { | ||
430 | commands = llCSV2List(str); | ||
431 | } else if (num == -3) { | ||
432 | menus = llCSV2List(str); | ||
433 | } else if (num == -4) { | ||
434 | buttonindex = llCSV2List(str); | ||
435 | } else if (num == -5) { | ||
436 | balls = llCSV2List(str); | ||
437 | } else if (num == -6) { | ||
438 | users = llCSV2List(str); | ||
439 | } else if (num == -7) { | ||
440 | LMButtons = llCSV2List(str); | ||
441 | } else if (num == -8) { | ||
442 | LMParms = llParseStringKeepNulls(str, ["|"], []); | ||
443 | } else if (num == -9) { | ||
444 | SoundNames = llCSV2List(str); | ||
445 | } else if (num == -10) { | ||
446 | Sounds = llCSV2List(str); | ||
447 | } else if (num == -20) { | ||
448 | list args = llCSV2List(str); | ||
449 | redo = llList2Integer(args,0); | ||
450 | chat = llList2Integer(args,1); | ||
451 | ballusers = llList2Integer(args,2); | ||
452 | menuusers = llList2Integer(args,3); | ||
453 | SaneMenuOrder = llList2Integer(args,4); | ||
454 | ReloadOnRez = llList2Integer(args,5); | ||
455 | |||
456 | state on; | ||
457 | } | ||
458 | } | ||
459 | |||
460 | state_exit() { | ||
461 | llOwnerSay("("+llGetScriptName()+": "+(string)llGetFreeMemory()+" bytes free)"); | ||
462 | llWhisper(0, Version + ": READY"); | ||
463 | } | ||
464 | } | ||
465 | |||
466 | state re_on { | ||
467 | state_entry() { | ||
468 | state on; | ||
469 | } | ||
470 | } | ||
471 | |||
472 | state on { | ||
473 | state_entry() { | ||
474 | ch = channel(); | ||
475 | owner = llGetOwner(); | ||
476 | llListen(ch - 1, "", NULL_KEY, ""); //listen for pressed buttons | ||
477 | // llWhisper(0, "Channel: " + (string)ch); | ||
478 | } | ||
479 | |||
480 | on_rez(integer arg) { | ||
481 | if (ReloadOnRez) { | ||
482 | llResetScript(); | ||
483 | } | ||
484 | BallCount = 0; | ||
485 | llSetTimerEvent(0.0); | ||
486 | state re_on; | ||
487 | } | ||
488 | |||
489 | touch_start(integer tcount) { | ||
490 | user0 = llDetectedKey(0); | ||
491 | touched(llDetectedGroup(0)); | ||
492 | } | ||
493 | |||
494 | listen(integer channel, string name, key id, string button) { | ||
495 | if (id != user) { | ||
496 | if (button == "Yes") { | ||
497 | user = id; | ||
498 | group = llSameGroup(user0); | ||
499 | mainMenu(); | ||
500 | } else if (button != "Cancel") { | ||
501 | continMenu("Selection cancelled because "); | ||
502 | } | ||
503 | return; | ||
504 | } | ||
505 | if (handle_cmd(button, FALSE) && redo) doMenu(FALSE); | ||
506 | } | ||
507 | |||
508 | |||
509 | link_message(integer from, integer num, string str, key id) { | ||
510 | if (str == "PRIMTOUCH") { | ||
511 | user0 = id; | ||
512 | touched(num); | ||
513 | return; | ||
514 | } | ||
515 | if (num == 0 && str == "AGAIN") { | ||
516 | llMessageLinked(LINK_THIS,0,"POSE", Posemsg); //msg to pose | ||
517 | llMessageLinked(LINK_THIS,0,"POSEB", (key)pose); //msg to memory | ||
518 | return; | ||
519 | } | ||
520 | if (num == -12002) { | ||
521 | handle_cmd(str, TRUE); | ||
522 | return; | ||
523 | } | ||
524 | } | ||
525 | |||
526 | timer() { | ||
527 | setBalls("LIVE"); //msg to balls: stay alive | ||
528 | } | ||
529 | } | ||
diff --git a/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~menucfg.lsl b/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~menucfg.lsl new file mode 100644 index 0000000..d38843d --- /dev/null +++ b/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~menucfg.lsl | |||
@@ -0,0 +1,296 @@ | |||
1 | // MLPV2 Version 2.2, by Learjeff Innis, based on | ||
2 | // MLP MULTI-LOVE-POSE V1.2 - Copyright (c) 2006, by Miffy Fluffy (BSD License) | ||
3 | // 15-color balls by Lizz Silverstar | ||
4 | // autoback, multi-contin menu fixed | ||
5 | // OpenSim port by Jez Ember | ||
6 | // Meta 7 fixes by onefang Rejected | ||
7 | |||
8 | integer MAX_BALLS = 6; | ||
9 | |||
10 | // Multicolor ball patch by Lizz Silverstar | ||
11 | // The colors var used to store the color values is a 32 bit integer (0x00000000) | ||
12 | // This is broken up into 8 nibbles of which we will currently use the lower 4 nibbles | ||
13 | // the first ball color is in the lower 4 bits, the second in the next 4 bits, etc | ||
14 | // Masks and shifting are used to store and extract the data. | ||
15 | // 4 bits gives us 15 colors. 0 = no ball, 1-15 = color | ||
16 | // these index values are then used by the ~ball code to set the correct color | ||
17 | // 1st ball mask is 0x0000000F, no shift | ||
18 | // 2nd ball mask is 0x000000F0, shift of 4 | ||
19 | // 3rd ball mask is 0x00000F00, shift of 8 | ||
20 | // 4th ball mask is 0x0000F000, shift of 12 | ||
21 | |||
22 | list Colornames = [ | ||
23 | "HIDE", "PINK", "BLUE", "PINK2", | ||
24 | "BLUE2", "GREEN", "MAGENTA", "RED", | ||
25 | "ORANGE", "WHITE", "BLACK", "YELLOW", | ||
26 | "CYAN", "RED2", "TEAL", "GREEN2"]; | ||
27 | |||
28 | |||
29 | integer PoseIx; | ||
30 | |||
31 | integer CurButtonIx; // index of current button | ||
32 | integer b0; // index of current button from start of current menu | ||
33 | |||
34 | integer AutoBack; | ||
35 | integer chat = TRUE; | ||
36 | integer redo = TRUE; | ||
37 | integer menuusers; | ||
38 | integer group; | ||
39 | integer ballusers; | ||
40 | integer SaneMenuOrder; | ||
41 | integer ReloadOnRez = FALSE; | ||
42 | |||
43 | string cmd; | ||
44 | string pose; | ||
45 | string pose0; | ||
46 | |||
47 | list buttons; | ||
48 | list buttonindex; | ||
49 | list commands; | ||
50 | list menus; | ||
51 | list balls; | ||
52 | list users; | ||
53 | |||
54 | list SoundNames; | ||
55 | list Sounds; | ||
56 | list LMButtons; | ||
57 | list LMParms; | ||
58 | |||
59 | |||
60 | // Globals for reading card config | ||
61 | integer ConfigLineIndex; | ||
62 | list ConfigCards; // list of names of config cards | ||
63 | string ConfigCardName; // name of card being read | ||
64 | integer ConfigCardIndex; // index of next card to read | ||
65 | key ConfigQueryId; | ||
66 | |||
67 | // Replacement for llListFindList which is currently broken in OSLSL | ||
68 | integer myListFind(list a, string b) { | ||
69 | integer x; | ||
70 | integer l=llGetListLength(a); | ||
71 | |||
72 | for(x=0; x<l; x++) { | ||
73 | if(llList2String(a,x) == b) { | ||
74 | return x; | ||
75 | } | ||
76 | } | ||
77 | |||
78 | return -1; | ||
79 | } | ||
80 | |||
81 | integer next_card() | ||
82 | { | ||
83 | if (ConfigCardIndex >= llGetListLength(ConfigCards)) { | ||
84 | ConfigCards = []; | ||
85 | return (FALSE); | ||
86 | } | ||
87 | |||
88 | ConfigLineIndex = 0; | ||
89 | ConfigCardName = llList2String(ConfigCards, ConfigCardIndex); | ||
90 | ConfigCardIndex++; | ||
91 | ConfigQueryId = llGetNotecardLine(ConfigCardName, ConfigLineIndex); | ||
92 | llOwnerSay("Reading " + ConfigCardName); | ||
93 | return (TRUE); | ||
94 | } | ||
95 | |||
96 | default { | ||
97 | state_entry() { | ||
98 | // ch = (integer)("0x"+llGetSubString((string)llGetKey(),-4,-1)); //fixed channel for prim | ||
99 | llMessageLinked(LINK_THIS,1,"OK?",(key)""); //msg to memory: ask if ready | ||
100 | } | ||
101 | link_message(integer from, integer num, string str, key id) { | ||
102 | if (num == 2 && str == "OK") state load; //memory ready | ||
103 | } | ||
104 | } | ||
105 | |||
106 | |||
107 | state load { | ||
108 | state_entry() { | ||
109 | string item; | ||
110 | ConfigCards = []; | ||
111 | integer n = llGetInventoryNumber(INVENTORY_NOTECARD); | ||
112 | while (n-- > 0) { | ||
113 | item = llGetInventoryName(INVENTORY_NOTECARD, n); | ||
114 | if (llSubStringIndex(item, ".MENUITEMS") != -1) { | ||
115 | ConfigCards += (list) item; | ||
116 | } | ||
117 | } | ||
118 | |||
119 | ConfigCardIndex = 0; | ||
120 | ConfigCards = llListSort(ConfigCards, 1, TRUE); | ||
121 | next_card(); | ||
122 | } | ||
123 | |||
124 | dataserver(key query_id, string data) { | ||
125 | if (query_id != ConfigQueryId) { | ||
126 | return; | ||
127 | } | ||
128 | if (data == EOF) { | ||
129 | if (next_card()) { | ||
130 | return; | ||
131 | } | ||
132 | state on; | ||
133 | } | ||
134 | |||
135 | integer ix = llSubStringIndex(data,"//"); //remove comments | ||
136 | if (ix != -1) { | ||
137 | if (ix == 0) data = ""; | ||
138 | else data = llGetSubString(data, 0, ix - 1); | ||
139 | } | ||
140 | |||
141 | data = llStringTrim(data, STRING_TRIM_TAIL); | ||
142 | if (data != "") { | ||
143 | ix = llSubStringIndex(data," "); | ||
144 | cmd = data; | ||
145 | if (ix != -1) { //split command from data | ||
146 | cmd = llGetSubString(data, 0, ix - 1); | ||
147 | data = llGetSubString(data, ix+1, -1); | ||
148 | } | ||
149 | list ldata = llParseStringKeepNulls(data,[" | "," | "," | "," | "," |","| ","|"],[]); | ||
150 | string arg1 = llList2String(ldata, 0); | ||
151 | // llSay(0, cmd + ":" + data); | ||
152 | if (cmd == "MENU") { | ||
153 | integer auth; | ||
154 | |||
155 | if (PoseIx < 2) { | ||
156 | llOwnerSay("warning: first two items in .MENUITEMS must be: POSE stand / POSE default"); | ||
157 | } | ||
158 | llOwnerSay("loading '"+arg1+"' menu"); | ||
159 | |||
160 | if (llList2String(ldata, 1) == "GROUP") auth = 1; //access to submenus | ||
161 | else if (llList2String(ldata, 1) != "OWNER") auth = 2; //0=owner 1=group 2=all | ||
162 | |||
163 | integer colors; | ||
164 | string ball_color; | ||
165 | integer colorIx; | ||
166 | integer ixB; | ||
167 | for (ixB=0; ixB < MAX_BALLS; ++ixB) { // for each possible ball | ||
168 | ball_color = llList2String(ldata, ixB + 2); // get next color name from config | ||
169 | |||
170 | colorIx = myListFind(Colornames, ball_color); | ||
171 | |||
172 | if (colorIx != -1) { | ||
173 | colors += (colorIx << (4 * ixB)); // 4 = bits per color (16 colors) | ||
174 | } | ||
175 | } | ||
176 | |||
177 | menus += (list) arg1; | ||
178 | balls += (list) colors; | ||
179 | buttonindex += (list) CurButtonIx; | ||
180 | users += (list) auth; | ||
181 | |||
182 | // if (llListFindList(buttons, (list)arg1) == -1) { | ||
183 | |||
184 | if (myListFind(buttons, arg1) == -1) { | ||
185 | |||
186 | integer jx = myListFind(buttons, "-"); | ||
187 | |||
188 | if (jx != -1) { | ||
189 | buttons = llListReplaceList(buttons, (list)arg1, jx, jx); | ||
190 | // "TOMENU" is already in commands list from the 'TOMENU -' | ||
191 | } else if (CurButtonIx > 2) { | ||
192 | llOwnerSay("No unused 'TOMENU -' for " + arg1); | ||
193 | } | ||
194 | } | ||
195 | |||
196 | b0 = 0; | ||
197 | } else if (cmd == "AUTOBACK") { | ||
198 | AutoBack = (arg1 != "0"); | ||
199 | } else if (cmd == "NORELOAD") { | ||
200 | ReloadOnRez = (arg1 != "0"); // whether to reload menu on rez | ||
201 | } else if (cmd == "MENUORDER") { | ||
202 | SaneMenuOrder = (arg1 != "0"); // keep menu buttons in same order as in file | ||
203 | } else { | ||
204 | |||
205 | // automatic menu extension (don't do for main menu) | ||
206 | if (b0 == 12 && llGetListLength(menus) > 1) { | ||
207 | // Add a "more" button before last item | ||
208 | integer ixA = -1; | ||
209 | if (AutoBack) { | ||
210 | ixA = -2; | ||
211 | // Add a "BACK" button | ||
212 | buttons = llListInsertList(buttons, (list)"BACK", ixA); | ||
213 | commands = llListInsertList(commands, (list)"BACK", ixA); | ||
214 | ++CurButtonIx; | ||
215 | } | ||
216 | buttons = llListInsertList(buttons, (list)"More-->", ixA); | ||
217 | commands = llListInsertList(commands, (list)"MORE", ixA); | ||
218 | ++CurButtonIx; | ||
219 | b0 = -ixA; | ||
220 | } | ||
221 | if (cmd == "POSE") { | ||
222 | llMessageLinked(LINK_THIS,9+PoseIx,data, (key)""); | ||
223 | if (!PoseIx) pose0 = arg1; | ||
224 | cmd = (string)PoseIx; | ||
225 | ++PoseIx; | ||
226 | } else if (cmd == "REDO") { | ||
227 | if (llList2String(ldata, 1) != "OFF") redo = 1; | ||
228 | } else if (cmd == "CHAT") { | ||
229 | if (llList2String(ldata, 1) != "OFF") chat = 1; | ||
230 | } else if (cmd == "BALLUSERS") { | ||
231 | if (llList2String(ldata, 1) == "GROUP") ballusers = 1; | ||
232 | } else if (cmd == "MENUUSERS") { | ||
233 | if (llList2String(ldata, 1) == "GROUP") menuusers = 1; | ||
234 | else if (llList2String(ldata, 1) != "OWNER") menuusers = 2; | ||
235 | } else if (cmd == "LINKMSG") { | ||
236 | LMButtons += arg1; | ||
237 | LMParms += llList2String(ldata, 1); | ||
238 | } else if (cmd == "SOUND") { | ||
239 | SoundNames += (list) arg1; | ||
240 | Sounds += (list) llList2String(ldata, 1); | ||
241 | } | ||
242 | commands += (list) cmd; | ||
243 | buttons += (list) arg1; | ||
244 | ++CurButtonIx; | ||
245 | ++b0; | ||
246 | } | ||
247 | } | ||
248 | ++ConfigLineIndex; | ||
249 | ConfigQueryId = llGetNotecardLine(ConfigCardName, ConfigLineIndex); //read next line of menuitems notecard | ||
250 | } | ||
251 | state_exit() { | ||
252 | buttonindex += (list) CurButtonIx; //enter last buttonindex | ||
253 | commands += (list) ""; //empty command for undefined buttons (-1) | ||
254 | |||
255 | integer ix; | ||
256 | integer count; | ||
257 | while ((ix = myListFind(buttons, "-")) != -1) { | ||
258 | ++count; | ||
259 | buttons = llDeleteSubList(buttons, ix, ix); | ||
260 | commands = llDeleteSubList(commands, ix, ix); | ||
261 | } | ||
262 | if (count) { | ||
263 | for (ix = 1; ix < llGetListLength(buttonindex); ++ix) { | ||
264 | buttonindex = llListReplaceList(buttonindex, | ||
265 | (list)(llList2Integer(buttonindex, ix) - count), ix, ix); | ||
266 | } | ||
267 | } | ||
268 | // llMessageLinked(LINK_THIS,1,"LOADED",(string)PoseIx); //msg to memory | ||
269 | llMessageLinked(LINK_THIS,9+PoseIx,"LOADED",(key)""); //msg to pose | ||
270 | } | ||
271 | } | ||
272 | |||
273 | state on { | ||
274 | state_entry() { | ||
275 | llMessageLinked(LINK_THIS, -3, llList2CSV(menus), (key)""); menus = []; | ||
276 | llMessageLinked(LINK_THIS, -4, llList2CSV(buttonindex), (key)""); buttonindex = []; | ||
277 | llMessageLinked(LINK_THIS, -5, llList2CSV(balls), (key)""); balls = []; | ||
278 | llMessageLinked(LINK_THIS, -6, llList2CSV(users), (key)""); users = []; | ||
279 | llMessageLinked(LINK_THIS, -7, llList2CSV(LMButtons), (key)""); LMButtons = []; | ||
280 | |||
281 | llMessageLinked(LINK_THIS, -8, llDumpList2String(LMParms, "|"), (key)""); LMParms = []; | ||
282 | |||
283 | llMessageLinked(LINK_THIS, -9, llList2CSV(SoundNames), (key)""); SoundNames = []; | ||
284 | llMessageLinked(LINK_THIS, -10, llList2CSV(Sounds), (key)""); Sounds = []; | ||
285 | |||
286 | llMessageLinked(LINK_THIS, -2, llList2CSV(commands), (key)""); commands = []; | ||
287 | llMessageLinked(LINK_THIS, -1, llList2CSV(buttons), (key)""); buttons = []; | ||
288 | |||
289 | |||
290 | // finally, scalars (signals 'done' as well) | ||
291 | llMessageLinked(LINK_THIS, -20, | ||
292 | llList2CSV([ redo, chat, ballusers, menuusers, SaneMenuOrder, ReloadOnRez ]), (key)""); | ||
293 | |||
294 | llOwnerSay((string)CurButtonIx+" menuitems loaded ("+llGetScriptName()+": "+(string)llGetFreeMemory()+" bytes free)"); | ||
295 | } | ||
296 | } | ||
diff --git a/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~pos.lsl b/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~pos.lsl new file mode 100644 index 0000000..3b93b64 --- /dev/null +++ b/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~pos.lsl | |||
@@ -0,0 +1,108 @@ | |||
1 | // MLPV2 Version 2.3j, by Learjeff Innis, based on | ||
2 | //MLP MULTI-LOVE-POSE V1.2 - Copyright (c) 2006, by Miffy Fluffy (BSD License) | ||
3 | // OpenSim port by Jez Ember | ||
4 | // Meta 7 fixes by onefang Rejected and one by Tatjana Kidd. | ||
5 | |||
6 | integer MAX_BALLS = 6; | ||
7 | |||
8 | integer ch; | ||
9 | integer swap; | ||
10 | integer BallCount; | ||
11 | |||
12 | string pr1; | ||
13 | string pr2; | ||
14 | |||
15 | integer Zoffset; | ||
16 | |||
17 | vector RefPos; | ||
18 | rotation RefRot; | ||
19 | |||
20 | getRefPos() { //reference position | ||
21 | RefPos = llGetPos(); | ||
22 | RefRot = llGetRot(); | ||
23 | Zoffset = (integer)llGetObjectDesc(); | ||
24 | RefPos.z += (float) Zoffset / 100.; | ||
25 | } | ||
26 | |||
27 | list Pdata; | ||
28 | |||
29 | getPosNew(string pdata) { | ||
30 | Pdata = llParseString2List(pdata, [" "],[]); | ||
31 | } | ||
32 | |||
33 | setPos() { | ||
34 | pr1 = (string)((vector)llList2String(Pdata, 0) * RefRot + RefPos); | ||
35 | pr2 = (string)((vector)llList2String(Pdata, 2) * RefRot + RefPos); | ||
36 | pr1 += (string)(llEuler2Rot((vector)llList2String(Pdata, 1) * DEG_TO_RAD) * RefRot); | ||
37 | pr2 += (string)(llEuler2Rot((vector)llList2String(Pdata, 3) * DEG_TO_RAD) * RefRot); | ||
38 | if (BallCount > 1) { | ||
39 | llSay(ch+swap,pr1); //msg to ball1/2 | ||
40 | llSay(ch+!swap,pr2); | ||
41 | } else { | ||
42 | llSay(ch,pr1); //msg to ball1/2 | ||
43 | } | ||
44 | |||
45 | integer ix; | ||
46 | for (ix = 2; ix < BallCount; ++ix) { | ||
47 | llSay(ch + ix, (string)((vector)llList2String(Pdata, 2*ix) * RefRot + RefPos) | ||
48 | + (string)(llEuler2Rot((vector)llList2String(Pdata, 2*ix + 1) * DEG_TO_RAD) * RefRot)); | ||
49 | } | ||
50 | } | ||
51 | |||
52 | getChan() { | ||
53 | ch = (integer)("0x"+llGetSubString((string)llGetKey(),-4,-1)); //fixed channel for prim | ||
54 | } | ||
55 | |||
56 | default { | ||
57 | state_entry() { | ||
58 | getRefPos(); | ||
59 | getChan(); | ||
60 | } | ||
61 | |||
62 | on_rez(integer arg) { | ||
63 | getRefPos(); | ||
64 | getChan(); | ||
65 | } | ||
66 | |||
67 | link_message(integer from, integer num, string cmd, key pkey) { | ||
68 | if (cmd == "PRIMTOUCH"){ | ||
69 | return; | ||
70 | } | ||
71 | |||
72 | if (num == 1 && cmd == "STOP") { | ||
73 | swap = 0; | ||
74 | return; | ||
75 | } | ||
76 | |||
77 | if (num) return; | ||
78 | |||
79 | if (cmd == "POSE") { | ||
80 | list parms = llCSV2List((string)pkey); | ||
81 | BallCount = llList2Integer(parms,1); | ||
82 | return; | ||
83 | } else if (cmd == "POSEPOS") { | ||
84 | // p = (integer)((string)pkey | ||
85 | getPosNew((string)pkey); | ||
86 | setPos(); | ||
87 | } else if (cmd == "SWAP") { | ||
88 | swap = (integer)((string)pkey) & 1; | ||
89 | llSay(ch+swap,pr1); //msg to ball1/2 | ||
90 | llSay(ch+!swap,pr2); | ||
91 | } else if (cmd == "REPOS") { | ||
92 | getRefPos(); | ||
93 | } else if (llGetSubString(cmd, 0, 0) == "Z") { | ||
94 | // Changed by Tatjana to make it work :) | ||
95 | integer change; | ||
96 | if (llGetSubString(cmd,1,1) == "+") change = (integer)llGetSubString(cmd,2,10); | ||
97 | else change = (integer)llGetSubString(cmd,1,10); | ||
98 | // End Tatjana changing (Penny helped, of course!) | ||
99 | Zoffset += change; | ||
100 | RefPos.z += (float)change/100.; | ||
101 | setPos(); | ||
102 | llOwnerSay("Height Adjustment: change by " + (string) change + "cm, new offset: " + (string)Zoffset + "cm"); | ||
103 | llSetObjectDesc((string)Zoffset); | ||
104 | } else if (cmd == "GETREFPOS") { | ||
105 | llMessageLinked(LINK_THIS,8,(string)RefPos,(string)RefRot); //send reference position to pose | ||
106 | } | ||
107 | } | ||
108 | } | ||
diff --git a/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~pose.lsl b/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~pose.lsl new file mode 100644 index 0000000..26ab5ff --- /dev/null +++ b/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~pose.lsl | |||
@@ -0,0 +1,222 @@ | |||
1 | // MLPV2 Version 2.3, by Learjeff Innis, based on | ||
2 | // MLP MULTI-LOVE-POSE V1.2 - Copyright (c) 2006, by Miffy Fluffy (BSD License) | ||
3 | // OpenSim port by Jez Ember | ||
4 | // Meta 7 fixes by onefang Rejected | ||
5 | |||
6 | integer MAX_AVS = 6; | ||
7 | |||
8 | integer a; | ||
9 | integer ch; | ||
10 | integer i; | ||
11 | integer swap; | ||
12 | string an1; | ||
13 | string an2; | ||
14 | string an3; | ||
15 | string an4; | ||
16 | string an5; | ||
17 | string an6; | ||
18 | string pose; | ||
19 | |||
20 | list PRs; // pos/rot pairs for Save | ||
21 | |||
22 | list anims; // strided list of anims, indexed by pose*6 | ||
23 | vector pos; | ||
24 | rotation rot; | ||
25 | integer BallCount; // number of balls | ||
26 | integer UpdateCount; // number of balls we've heard from, for save | ||
27 | |||
28 | string prStr(string str) { | ||
29 | i = llSubStringIndex(str,">"); | ||
30 | vector p = ((vector)llGetSubString(str,0,i) - pos) / rot; | ||
31 | vector r = llRot2Euler((rotation)llGetSubString(str,i+1,-1) / rot)*RAD_TO_DEG; | ||
32 | return "<"+round(p.x, 3)+","+round(p.y, 3)+","+round(p.z, 3)+"> <"+round(r.x, 1)+","+round(r.y, 1)+","+round(r.z, 1)+">"; | ||
33 | } | ||
34 | |||
35 | string round(float number, integer places) { | ||
36 | float shifted; | ||
37 | integer rounded; | ||
38 | string s; | ||
39 | shifted = number * llPow(10.0,(float)places); | ||
40 | rounded = llRound(shifted); | ||
41 | s = (string)((float)rounded / llPow(10.0,(float)places)); | ||
42 | rounded = llSubStringIndex(s, "."); | ||
43 | if (-1 != rounded) | ||
44 | s = llGetSubString(s,0,llSubStringIndex(s, ".")+places); | ||
45 | else | ||
46 | { | ||
47 | s += ".00000000"; | ||
48 | s = llGetSubString(s,0,llSubStringIndex(s, ".")+places); | ||
49 | } | ||
50 | return s; | ||
51 | } | ||
52 | |||
53 | check_anim(string aname) { | ||
54 | if (aname == "") { | ||
55 | return; | ||
56 | } | ||
57 | if ( aname != "PINK" | ||
58 | && aname != "BLUE" | ||
59 | && aname != "stand" | ||
60 | && aname != "sit_ground") { | ||
61 | |||
62 | // ignore expression suffix of "*" or "::nnn" | ||
63 | if (llGetSubString(aname, -1, -1) == "*") { | ||
64 | aname = llGetSubString(aname, 0, -2); | ||
65 | } else { | ||
66 | integer ix = llSubStringIndex(aname, "::"); | ||
67 | if (ix != -1) { | ||
68 | aname = llGetSubString(aname, 0, ix-1); | ||
69 | } | ||
70 | } | ||
71 | |||
72 | if (llGetInventoryType(aname) != INVENTORY_ANIMATION) { | ||
73 | llSay(0,"animation '" | ||
74 | + aname | ||
75 | + "' not in inventory (ok for build-in animations, otherwise check)"); | ||
76 | } | ||
77 | } | ||
78 | } | ||
79 | |||
80 | getChan() { | ||
81 | ch = (integer)("0x"+llGetSubString((string)llGetKey(),-4,-1)); //fixed channel for prim | ||
82 | } | ||
83 | |||
84 | default { | ||
85 | |||
86 | link_message(integer from, integer num, string data, key id) { | ||
87 | if (num != 9+a) return; | ||
88 | |||
89 | if (data == "LOADED") state on; | ||
90 | |||
91 | list ldata = llParseString2List(data,[" | "," | "," | "," | "," |","| ","|"],[]); | ||
92 | |||
93 | an1 = llList2String(ldata,1); | ||
94 | an2 = llList2String(ldata,2); | ||
95 | an3 = llList2String(ldata,3); | ||
96 | an4 = llList2String(ldata,4); | ||
97 | an5 = llList2String(ldata,5); | ||
98 | an6 = llList2String(ldata,6); | ||
99 | |||
100 | if (a>1) { | ||
101 | check_anim(an1); | ||
102 | check_anim(an2); | ||
103 | check_anim(an3); | ||
104 | check_anim(an4); | ||
105 | check_anim(an5); | ||
106 | check_anim(an6); | ||
107 | } else if (a) { //pose1: set default | ||
108 | if (an1 == "") an1 = "sit_ground"; | ||
109 | if (an2 == "") an2 = "sit_ground"; | ||
110 | if (an3 == "") an3 = "sit_ground"; | ||
111 | if (an4 == "") an4 = "sit_ground"; | ||
112 | if (an5 == "") an5 = "sit_ground"; | ||
113 | if (an6 == "") an6 = "sit_ground"; | ||
114 | } else { //pose0: set stand | ||
115 | if (an1 == "") an1 = "stand"; | ||
116 | if (an2 == "") an2 = "stand"; | ||
117 | if (an3 == "") an3 = "stand"; | ||
118 | if (an4 == "") an4 = "stand"; | ||
119 | if (an5 == "") an5 = "stand"; | ||
120 | if (an6 == "") an6 = "stand"; | ||
121 | } | ||
122 | anims += [ an1, an2, an3, an4, an5, an6 ]; | ||
123 | ++a; | ||
124 | } | ||
125 | state_exit() { | ||
126 | llOwnerSay((string)a+" poses loaded ("+llGetScriptName()+": "+(string)llGetFreeMemory()+" bytes free)"); | ||
127 | } | ||
128 | } | ||
129 | |||
130 | |||
131 | state on { | ||
132 | state_entry() { | ||
133 | getChan(); | ||
134 | } | ||
135 | |||
136 | on_rez(integer arg) { | ||
137 | getChan(); | ||
138 | } | ||
139 | |||
140 | link_message(integer from, integer num, string cmd, key akey) { | ||
141 | if (cmd == "PRIMTOUCH"){ | ||
142 | return; | ||
143 | } | ||
144 | if (num) return; | ||
145 | if (cmd == "POSE") { | ||
146 | list parms = llCSV2List((string)akey); | ||
147 | BallCount = llList2Integer(parms,1); | ||
148 | a = llList2Integer(parms,0) * 6; | ||
149 | an1 = llList2String(anims, a); | ||
150 | an2 = llList2String(anims, a+1); | ||
151 | an3 = llList2String(anims, a+2); | ||
152 | an4 = llList2String(anims, a+3); | ||
153 | an5 = llList2String(anims, a+4); | ||
154 | an6 = llList2String(anims, a+5); | ||
155 | } else if (cmd == "SWAP") { | ||
156 | swap = !swap; | ||
157 | } else if (cmd == "SAVE") { | ||
158 | pose = (string)akey; | ||
159 | state save; | ||
160 | } else return; | ||
161 | llMessageLinked(LINK_THIS,ch+swap, an1,(key)""); //msg to poser 1/2 | ||
162 | llMessageLinked(LINK_THIS,ch+!swap,an2,(key)""); | ||
163 | llMessageLinked(LINK_THIS,ch+2, an3,(key)""); //msg to poser 3 | ||
164 | llMessageLinked(LINK_THIS,ch+3, an4,(key)""); //msg to poser 4 | ||
165 | llMessageLinked(LINK_THIS,ch+4, an5,(key)""); //msg to poser 4 | ||
166 | llMessageLinked(LINK_THIS,ch+5, an6,(key)""); //msg to poser 4 | ||
167 | } | ||
168 | } | ||
169 | |||
170 | state save { | ||
171 | state_entry() { | ||
172 | llMessageLinked(LINK_THIS,0,"GETREFPOS",""); //msg to pos: ask ref position | ||
173 | integer ix; | ||
174 | PRs = [ "", "", "", "", "", "" ]; | ||
175 | |||
176 | for (ix = 0; ix < MAX_AVS; ++ix) { | ||
177 | llListen(ch+16+ix, "", NULL_KEY, ""); | ||
178 | llSay(ch+ix,"SAVE"); //msg to balls | ||
179 | } | ||
180 | llSetTimerEvent(3); | ||
181 | UpdateCount = 0; | ||
182 | } | ||
183 | |||
184 | |||
185 | listen(integer channel, string name, key id, string pr) { | ||
186 | channel -= (ch + 16); | ||
187 | |||
188 | if (channel == 0) { | ||
189 | channel = channel + swap; | ||
190 | } else if (channel == 1) { | ||
191 | channel = channel - swap; | ||
192 | } | ||
193 | |||
194 | PRs = llListReplaceList(PRs, (list)pr, channel, channel); | ||
195 | |||
196 | if (++UpdateCount == BallCount) { | ||
197 | pr = ""; | ||
198 | integer ix; | ||
199 | for (ix = 0; ix < BallCount; ++ix) { | ||
200 | pr += prStr(llList2String(PRs, ix)) + " "; | ||
201 | } | ||
202 | |||
203 | llOwnerSay("{"+pose+"} "+pr); | ||
204 | llMessageLinked(LINK_THIS,1,pose,pr); //write to memory | ||
205 | state on; | ||
206 | } | ||
207 | } | ||
208 | link_message(integer from, integer num, string posstr, key rotkey) { | ||
209 | if (posstr == "PRIMTOUCH"){ | ||
210 | return; | ||
211 | } | ||
212 | if (num != 8) return; | ||
213 | pos = (vector)posstr; //revtrieve reference position from pos | ||
214 | rot = (rotation)((string)rotkey); | ||
215 | } | ||
216 | timer() { | ||
217 | state on; | ||
218 | } | ||
219 | state_exit() { | ||
220 | llSetTimerEvent(0); | ||
221 | } | ||
222 | } | ||
diff --git a/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~poser 1.lsl b/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~poser 1.lsl new file mode 100644 index 0000000..fc976c4 --- /dev/null +++ b/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~poser 1.lsl | |||
@@ -0,0 +1,200 @@ | |||
1 | // MPLV2 2.3 by Learjeff Innis, based on | ||
2 | // MLP MULTI-LOVE-POSE V1.2 - Copyright (c) 2006, by Miffy Fluffy (BSD License) | ||
3 | // OpenSim port by Jez Ember | ||
4 | // Meta 7 fixes by onefang Rejected | ||
5 | |||
6 | integer ch; | ||
7 | string animation = "stand"; | ||
8 | key avatar; | ||
9 | |||
10 | integer ExprEnabled = TRUE; | ||
11 | string Expression; | ||
12 | float ExprTimer; | ||
13 | |||
14 | integer BallNum; | ||
15 | |||
16 | list Expressions = [ | ||
17 | "" | ||
18 | , "express_open_mouth" // 1 | ||
19 | , "express_surprise_emote" // 2 | ||
20 | , "express_tongue_out" // 3 | ||
21 | , "express_smile" // 4 | ||
22 | , "express_toothsmile" // 5 | ||
23 | , "express_wink_emote" // 6 | ||
24 | , "express_cry_emote" // 7 | ||
25 | , "express_kiss" // 8 | ||
26 | , "express_laugh_emote" // 9 | ||
27 | , "express_disdain" // 10 | ||
28 | , "express_repulsed_emote" // 11 | ||
29 | , "express_anger_emote" // 12 | ||
30 | , "express_bored_emote" // 13 | ||
31 | , "express_sad_emote" // 14 | ||
32 | , "express_embarrassed_emote" // 15 | ||
33 | , "express_frown" // 16 | ||
34 | , "express_shrug_emote" // 17 | ||
35 | , "express_afraid_emote" // 18 | ||
36 | , "express_worry_emote" // 19 | ||
37 | , "SLEEP" // 20 | ||
38 | ]; | ||
39 | |||
40 | |||
41 | stopAnim() { | ||
42 | key id = llGetPermissionsKey(); | ||
43 | list anims = llGetAnimationList(id); | ||
44 | integer ix; | ||
45 | for (ix = 0; ix < llGetListLength(anims); ++ix) { | ||
46 | string anim = llList2String(anims, ix); | ||
47 | if (anim != "") { | ||
48 | llStopAnimation(anim); | ||
49 | } | ||
50 | } | ||
51 | llSetTimerEvent(0.0); | ||
52 | } | ||
53 | |||
54 | startAnim(string anim) { | ||
55 | if (Expression != "") { | ||
56 | if (Expression == "SLEEP") { | ||
57 | llStartAnimation("express_disdain"); | ||
58 | llStartAnimation("express_smile"); | ||
59 | } else { | ||
60 | llStartAnimation(Expression); | ||
61 | } | ||
62 | if (ExprEnabled) { | ||
63 | llSetTimerEvent(ExprTimer); | ||
64 | } | ||
65 | } else { | ||
66 | stopAnim(); | ||
67 | } | ||
68 | if (anim != "") { | ||
69 | llStartAnimation(anim); | ||
70 | } | ||
71 | } | ||
72 | |||
73 | // Animation names with a "*" suffix get open mouth | ||
74 | // Those with a suffix of "::" followed by a number | ||
75 | // get the expression associated with that number. | ||
76 | // This can optionally be followed by another "::" delim, | ||
77 | // with a timer value following. | ||
78 | // Return the anim name without the suffix. | ||
79 | string getExpression(string anim) { | ||
80 | if (llGetSubString(anim,-1,-1) == "*") { | ||
81 | Expression = llList2String(Expressions, 1); | ||
82 | ExprTimer = 0.5; | ||
83 | return llGetSubString(anim, 0, -2); | ||
84 | } | ||
85 | integer ix = llSubStringIndex(anim, "::"); | ||
86 | if (ix == -1) { | ||
87 | Expression = ""; | ||
88 | ExprTimer = 0.5; | ||
89 | return anim; | ||
90 | } | ||
91 | |||
92 | list parms = llParseString2List(anim, ["::"], []); | ||
93 | anim = llList2String(parms, 0); | ||
94 | integer exprIx = (integer) llList2String(parms, 1); | ||
95 | Expression = llList2String(Expressions, exprIx); | ||
96 | ExprTimer = (float) llList2String(parms,2); | ||
97 | |||
98 | if (ExprTimer <= 0.0) { | ||
99 | ExprTimer = 0.5; | ||
100 | } | ||
101 | |||
102 | return anim; | ||
103 | } | ||
104 | |||
105 | getChan() { | ||
106 | BallNum = (integer) llGetSubString(llGetScriptName(),-1,-1); //offset from script name suffix | ||
107 | ch = BallNum | ||
108 | + (integer)("0x"+llGetSubString((string)llGetKey(),-4,-1)); //fixed channel for prim | ||
109 | } | ||
110 | |||
111 | default { | ||
112 | state_entry() { | ||
113 | state s_on; | ||
114 | } | ||
115 | } | ||
116 | |||
117 | state s_on { | ||
118 | state_entry() { | ||
119 | getChan(); | ||
120 | llListen(ch+8,"",NULL_KEY,""); | ||
121 | } | ||
122 | |||
123 | on_rez(integer arg) { | ||
124 | state default; | ||
125 | } | ||
126 | |||
127 | link_message(integer from, integer num, string an, key id) { //an animation is set | ||
128 | if (an == "PRIMTOUCH") { | ||
129 | return; | ||
130 | } | ||
131 | |||
132 | if (num != ch) return; | ||
133 | an = getExpression(an); // get & save expression, and return unadorned anim | ||
134 | |||
135 | if (avatar == llGetPermissionsKey() | ||
136 | && avatar != NULL_KEY | ||
137 | && animation != "") { | ||
138 | llStopAnimation(animation); | ||
139 | llMessageLinked(LINK_SET, -11002, (string)BallNum + "|" + an, avatar); | ||
140 | startAnim(an); | ||
141 | } | ||
142 | animation = an; | ||
143 | } | ||
144 | |||
145 | timer() { // timer to keep mouth open | ||
146 | if (Expression == "SLEEP") { | ||
147 | llStartAnimation("express_disdain"); | ||
148 | llStartAnimation("express_smile"); | ||
149 | } else if (Expression != "") { | ||
150 | llStartAnimation(Expression); | ||
151 | } | ||
152 | } | ||
153 | |||
154 | listen(integer channel, string name, key id, string str) { | ||
155 | if (str == "ALIVE" || str == "DIE") { | ||
156 | llMessageLinked(LINK_THIS,2,str,""); //send msg from ball to menu | ||
157 | if (str == "DIE") { | ||
158 | avatar = NULL_KEY; | ||
159 | llSetTimerEvent(0.0); | ||
160 | } | ||
161 | return; | ||
162 | } | ||
163 | |||
164 | avatar = (key) str; //avatar (sit) or NULL_KEY (stand up) | ||
165 | if (avatar == NULL_KEY) { | ||
166 | if (llGetPermissions() & PERMISSION_TRIGGER_ANIMATION) { | ||
167 | stopAnim(); | ||
168 | llMessageLinked(LINK_SET, -11001, (string)BallNum, llGetPermissionsKey()); | ||
169 | } | ||
170 | // llReleaseControls(); | ||
171 | return; | ||
172 | } | ||
173 | |||
174 | if (avatar != llGetPermissionsKey() | ||
175 | || ! (llGetPermissions() & PERMISSION_TRIGGER_ANIMATION)) { | ||
176 | ExprEnabled = TRUE; | ||
177 | llRequestPermissions(avatar, PERMISSION_TRIGGER_ANIMATION); | ||
178 | } else { | ||
179 | stopAnim(); | ||
180 | llMessageLinked(LINK_SET, -11000, (string)BallNum + "|" + animation, avatar); | ||
181 | startAnim(animation); | ||
182 | } | ||
183 | } | ||
184 | |||
185 | run_time_permissions(integer perm) { | ||
186 | if (avatar != llGetPermissionsKey()) { | ||
187 | llWhisper(DEBUG_CHANNEL, "avatar != perm key"); | ||
188 | return; | ||
189 | } | ||
190 | |||
191 | if (perm & PERMISSION_TRIGGER_ANIMATION) { | ||
192 | stopAnim(); | ||
193 | llMessageLinked(LINK_SET, -11000, (string)BallNum + "|" + animation, avatar); | ||
194 | startAnim(animation); | ||
195 | } else { | ||
196 | llMessageLinked(LINK_SET, -11001, (string)BallNum, avatar); | ||
197 | llSetTimerEvent(0.0); | ||
198 | } | ||
199 | } | ||
200 | } | ||
diff --git a/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~poser 2.lsl b/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~poser 2.lsl new file mode 100644 index 0000000..fc976c4 --- /dev/null +++ b/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~poser 2.lsl | |||
@@ -0,0 +1,200 @@ | |||
1 | // MPLV2 2.3 by Learjeff Innis, based on | ||
2 | // MLP MULTI-LOVE-POSE V1.2 - Copyright (c) 2006, by Miffy Fluffy (BSD License) | ||
3 | // OpenSim port by Jez Ember | ||
4 | // Meta 7 fixes by onefang Rejected | ||
5 | |||
6 | integer ch; | ||
7 | string animation = "stand"; | ||
8 | key avatar; | ||
9 | |||
10 | integer ExprEnabled = TRUE; | ||
11 | string Expression; | ||
12 | float ExprTimer; | ||
13 | |||
14 | integer BallNum; | ||
15 | |||
16 | list Expressions = [ | ||
17 | "" | ||
18 | , "express_open_mouth" // 1 | ||
19 | , "express_surprise_emote" // 2 | ||
20 | , "express_tongue_out" // 3 | ||
21 | , "express_smile" // 4 | ||
22 | , "express_toothsmile" // 5 | ||
23 | , "express_wink_emote" // 6 | ||
24 | , "express_cry_emote" // 7 | ||
25 | , "express_kiss" // 8 | ||
26 | , "express_laugh_emote" // 9 | ||
27 | , "express_disdain" // 10 | ||
28 | , "express_repulsed_emote" // 11 | ||
29 | , "express_anger_emote" // 12 | ||
30 | , "express_bored_emote" // 13 | ||
31 | , "express_sad_emote" // 14 | ||
32 | , "express_embarrassed_emote" // 15 | ||
33 | , "express_frown" // 16 | ||
34 | , "express_shrug_emote" // 17 | ||
35 | , "express_afraid_emote" // 18 | ||
36 | , "express_worry_emote" // 19 | ||
37 | , "SLEEP" // 20 | ||
38 | ]; | ||
39 | |||
40 | |||
41 | stopAnim() { | ||
42 | key id = llGetPermissionsKey(); | ||
43 | list anims = llGetAnimationList(id); | ||
44 | integer ix; | ||
45 | for (ix = 0; ix < llGetListLength(anims); ++ix) { | ||
46 | string anim = llList2String(anims, ix); | ||
47 | if (anim != "") { | ||
48 | llStopAnimation(anim); | ||
49 | } | ||
50 | } | ||
51 | llSetTimerEvent(0.0); | ||
52 | } | ||
53 | |||
54 | startAnim(string anim) { | ||
55 | if (Expression != "") { | ||
56 | if (Expression == "SLEEP") { | ||
57 | llStartAnimation("express_disdain"); | ||
58 | llStartAnimation("express_smile"); | ||
59 | } else { | ||
60 | llStartAnimation(Expression); | ||
61 | } | ||
62 | if (ExprEnabled) { | ||
63 | llSetTimerEvent(ExprTimer); | ||
64 | } | ||
65 | } else { | ||
66 | stopAnim(); | ||
67 | } | ||
68 | if (anim != "") { | ||
69 | llStartAnimation(anim); | ||
70 | } | ||
71 | } | ||
72 | |||
73 | // Animation names with a "*" suffix get open mouth | ||
74 | // Those with a suffix of "::" followed by a number | ||
75 | // get the expression associated with that number. | ||
76 | // This can optionally be followed by another "::" delim, | ||
77 | // with a timer value following. | ||
78 | // Return the anim name without the suffix. | ||
79 | string getExpression(string anim) { | ||
80 | if (llGetSubString(anim,-1,-1) == "*") { | ||
81 | Expression = llList2String(Expressions, 1); | ||
82 | ExprTimer = 0.5; | ||
83 | return llGetSubString(anim, 0, -2); | ||
84 | } | ||
85 | integer ix = llSubStringIndex(anim, "::"); | ||
86 | if (ix == -1) { | ||
87 | Expression = ""; | ||
88 | ExprTimer = 0.5; | ||
89 | return anim; | ||
90 | } | ||
91 | |||
92 | list parms = llParseString2List(anim, ["::"], []); | ||
93 | anim = llList2String(parms, 0); | ||
94 | integer exprIx = (integer) llList2String(parms, 1); | ||
95 | Expression = llList2String(Expressions, exprIx); | ||
96 | ExprTimer = (float) llList2String(parms,2); | ||
97 | |||
98 | if (ExprTimer <= 0.0) { | ||
99 | ExprTimer = 0.5; | ||
100 | } | ||
101 | |||
102 | return anim; | ||
103 | } | ||
104 | |||
105 | getChan() { | ||
106 | BallNum = (integer) llGetSubString(llGetScriptName(),-1,-1); //offset from script name suffix | ||
107 | ch = BallNum | ||
108 | + (integer)("0x"+llGetSubString((string)llGetKey(),-4,-1)); //fixed channel for prim | ||
109 | } | ||
110 | |||
111 | default { | ||
112 | state_entry() { | ||
113 | state s_on; | ||
114 | } | ||
115 | } | ||
116 | |||
117 | state s_on { | ||
118 | state_entry() { | ||
119 | getChan(); | ||
120 | llListen(ch+8,"",NULL_KEY,""); | ||
121 | } | ||
122 | |||
123 | on_rez(integer arg) { | ||
124 | state default; | ||
125 | } | ||
126 | |||
127 | link_message(integer from, integer num, string an, key id) { //an animation is set | ||
128 | if (an == "PRIMTOUCH") { | ||
129 | return; | ||
130 | } | ||
131 | |||
132 | if (num != ch) return; | ||
133 | an = getExpression(an); // get & save expression, and return unadorned anim | ||
134 | |||
135 | if (avatar == llGetPermissionsKey() | ||
136 | && avatar != NULL_KEY | ||
137 | && animation != "") { | ||
138 | llStopAnimation(animation); | ||
139 | llMessageLinked(LINK_SET, -11002, (string)BallNum + "|" + an, avatar); | ||
140 | startAnim(an); | ||
141 | } | ||
142 | animation = an; | ||
143 | } | ||
144 | |||
145 | timer() { // timer to keep mouth open | ||
146 | if (Expression == "SLEEP") { | ||
147 | llStartAnimation("express_disdain"); | ||
148 | llStartAnimation("express_smile"); | ||
149 | } else if (Expression != "") { | ||
150 | llStartAnimation(Expression); | ||
151 | } | ||
152 | } | ||
153 | |||
154 | listen(integer channel, string name, key id, string str) { | ||
155 | if (str == "ALIVE" || str == "DIE") { | ||
156 | llMessageLinked(LINK_THIS,2,str,""); //send msg from ball to menu | ||
157 | if (str == "DIE") { | ||
158 | avatar = NULL_KEY; | ||
159 | llSetTimerEvent(0.0); | ||
160 | } | ||
161 | return; | ||
162 | } | ||
163 | |||
164 | avatar = (key) str; //avatar (sit) or NULL_KEY (stand up) | ||
165 | if (avatar == NULL_KEY) { | ||
166 | if (llGetPermissions() & PERMISSION_TRIGGER_ANIMATION) { | ||
167 | stopAnim(); | ||
168 | llMessageLinked(LINK_SET, -11001, (string)BallNum, llGetPermissionsKey()); | ||
169 | } | ||
170 | // llReleaseControls(); | ||
171 | return; | ||
172 | } | ||
173 | |||
174 | if (avatar != llGetPermissionsKey() | ||
175 | || ! (llGetPermissions() & PERMISSION_TRIGGER_ANIMATION)) { | ||
176 | ExprEnabled = TRUE; | ||
177 | llRequestPermissions(avatar, PERMISSION_TRIGGER_ANIMATION); | ||
178 | } else { | ||
179 | stopAnim(); | ||
180 | llMessageLinked(LINK_SET, -11000, (string)BallNum + "|" + animation, avatar); | ||
181 | startAnim(animation); | ||
182 | } | ||
183 | } | ||
184 | |||
185 | run_time_permissions(integer perm) { | ||
186 | if (avatar != llGetPermissionsKey()) { | ||
187 | llWhisper(DEBUG_CHANNEL, "avatar != perm key"); | ||
188 | return; | ||
189 | } | ||
190 | |||
191 | if (perm & PERMISSION_TRIGGER_ANIMATION) { | ||
192 | stopAnim(); | ||
193 | llMessageLinked(LINK_SET, -11000, (string)BallNum + "|" + animation, avatar); | ||
194 | startAnim(animation); | ||
195 | } else { | ||
196 | llMessageLinked(LINK_SET, -11001, (string)BallNum, avatar); | ||
197 | llSetTimerEvent(0.0); | ||
198 | } | ||
199 | } | ||
200 | } | ||
diff --git a/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~poser 3.lsl b/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~poser 3.lsl new file mode 100644 index 0000000..fc976c4 --- /dev/null +++ b/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~poser 3.lsl | |||
@@ -0,0 +1,200 @@ | |||
1 | // MPLV2 2.3 by Learjeff Innis, based on | ||
2 | // MLP MULTI-LOVE-POSE V1.2 - Copyright (c) 2006, by Miffy Fluffy (BSD License) | ||
3 | // OpenSim port by Jez Ember | ||
4 | // Meta 7 fixes by onefang Rejected | ||
5 | |||
6 | integer ch; | ||
7 | string animation = "stand"; | ||
8 | key avatar; | ||
9 | |||
10 | integer ExprEnabled = TRUE; | ||
11 | string Expression; | ||
12 | float ExprTimer; | ||
13 | |||
14 | integer BallNum; | ||
15 | |||
16 | list Expressions = [ | ||
17 | "" | ||
18 | , "express_open_mouth" // 1 | ||
19 | , "express_surprise_emote" // 2 | ||
20 | , "express_tongue_out" // 3 | ||
21 | , "express_smile" // 4 | ||
22 | , "express_toothsmile" // 5 | ||
23 | , "express_wink_emote" // 6 | ||
24 | , "express_cry_emote" // 7 | ||
25 | , "express_kiss" // 8 | ||
26 | , "express_laugh_emote" // 9 | ||
27 | , "express_disdain" // 10 | ||
28 | , "express_repulsed_emote" // 11 | ||
29 | , "express_anger_emote" // 12 | ||
30 | , "express_bored_emote" // 13 | ||
31 | , "express_sad_emote" // 14 | ||
32 | , "express_embarrassed_emote" // 15 | ||
33 | , "express_frown" // 16 | ||
34 | , "express_shrug_emote" // 17 | ||
35 | , "express_afraid_emote" // 18 | ||
36 | , "express_worry_emote" // 19 | ||
37 | , "SLEEP" // 20 | ||
38 | ]; | ||
39 | |||
40 | |||
41 | stopAnim() { | ||
42 | key id = llGetPermissionsKey(); | ||
43 | list anims = llGetAnimationList(id); | ||
44 | integer ix; | ||
45 | for (ix = 0; ix < llGetListLength(anims); ++ix) { | ||
46 | string anim = llList2String(anims, ix); | ||
47 | if (anim != "") { | ||
48 | llStopAnimation(anim); | ||
49 | } | ||
50 | } | ||
51 | llSetTimerEvent(0.0); | ||
52 | } | ||
53 | |||
54 | startAnim(string anim) { | ||
55 | if (Expression != "") { | ||
56 | if (Expression == "SLEEP") { | ||
57 | llStartAnimation("express_disdain"); | ||
58 | llStartAnimation("express_smile"); | ||
59 | } else { | ||
60 | llStartAnimation(Expression); | ||
61 | } | ||
62 | if (ExprEnabled) { | ||
63 | llSetTimerEvent(ExprTimer); | ||
64 | } | ||
65 | } else { | ||
66 | stopAnim(); | ||
67 | } | ||
68 | if (anim != "") { | ||
69 | llStartAnimation(anim); | ||
70 | } | ||
71 | } | ||
72 | |||
73 | // Animation names with a "*" suffix get open mouth | ||
74 | // Those with a suffix of "::" followed by a number | ||
75 | // get the expression associated with that number. | ||
76 | // This can optionally be followed by another "::" delim, | ||
77 | // with a timer value following. | ||
78 | // Return the anim name without the suffix. | ||
79 | string getExpression(string anim) { | ||
80 | if (llGetSubString(anim,-1,-1) == "*") { | ||
81 | Expression = llList2String(Expressions, 1); | ||
82 | ExprTimer = 0.5; | ||
83 | return llGetSubString(anim, 0, -2); | ||
84 | } | ||
85 | integer ix = llSubStringIndex(anim, "::"); | ||
86 | if (ix == -1) { | ||
87 | Expression = ""; | ||
88 | ExprTimer = 0.5; | ||
89 | return anim; | ||
90 | } | ||
91 | |||
92 | list parms = llParseString2List(anim, ["::"], []); | ||
93 | anim = llList2String(parms, 0); | ||
94 | integer exprIx = (integer) llList2String(parms, 1); | ||
95 | Expression = llList2String(Expressions, exprIx); | ||
96 | ExprTimer = (float) llList2String(parms,2); | ||
97 | |||
98 | if (ExprTimer <= 0.0) { | ||
99 | ExprTimer = 0.5; | ||
100 | } | ||
101 | |||
102 | return anim; | ||
103 | } | ||
104 | |||
105 | getChan() { | ||
106 | BallNum = (integer) llGetSubString(llGetScriptName(),-1,-1); //offset from script name suffix | ||
107 | ch = BallNum | ||
108 | + (integer)("0x"+llGetSubString((string)llGetKey(),-4,-1)); //fixed channel for prim | ||
109 | } | ||
110 | |||
111 | default { | ||
112 | state_entry() { | ||
113 | state s_on; | ||
114 | } | ||
115 | } | ||
116 | |||
117 | state s_on { | ||
118 | state_entry() { | ||
119 | getChan(); | ||
120 | llListen(ch+8,"",NULL_KEY,""); | ||
121 | } | ||
122 | |||
123 | on_rez(integer arg) { | ||
124 | state default; | ||
125 | } | ||
126 | |||
127 | link_message(integer from, integer num, string an, key id) { //an animation is set | ||
128 | if (an == "PRIMTOUCH") { | ||
129 | return; | ||
130 | } | ||
131 | |||
132 | if (num != ch) return; | ||
133 | an = getExpression(an); // get & save expression, and return unadorned anim | ||
134 | |||
135 | if (avatar == llGetPermissionsKey() | ||
136 | && avatar != NULL_KEY | ||
137 | && animation != "") { | ||
138 | llStopAnimation(animation); | ||
139 | llMessageLinked(LINK_SET, -11002, (string)BallNum + "|" + an, avatar); | ||
140 | startAnim(an); | ||
141 | } | ||
142 | animation = an; | ||
143 | } | ||
144 | |||
145 | timer() { // timer to keep mouth open | ||
146 | if (Expression == "SLEEP") { | ||
147 | llStartAnimation("express_disdain"); | ||
148 | llStartAnimation("express_smile"); | ||
149 | } else if (Expression != "") { | ||
150 | llStartAnimation(Expression); | ||
151 | } | ||
152 | } | ||
153 | |||
154 | listen(integer channel, string name, key id, string str) { | ||
155 | if (str == "ALIVE" || str == "DIE") { | ||
156 | llMessageLinked(LINK_THIS,2,str,""); //send msg from ball to menu | ||
157 | if (str == "DIE") { | ||
158 | avatar = NULL_KEY; | ||
159 | llSetTimerEvent(0.0); | ||
160 | } | ||
161 | return; | ||
162 | } | ||
163 | |||
164 | avatar = (key) str; //avatar (sit) or NULL_KEY (stand up) | ||
165 | if (avatar == NULL_KEY) { | ||
166 | if (llGetPermissions() & PERMISSION_TRIGGER_ANIMATION) { | ||
167 | stopAnim(); | ||
168 | llMessageLinked(LINK_SET, -11001, (string)BallNum, llGetPermissionsKey()); | ||
169 | } | ||
170 | // llReleaseControls(); | ||
171 | return; | ||
172 | } | ||
173 | |||
174 | if (avatar != llGetPermissionsKey() | ||
175 | || ! (llGetPermissions() & PERMISSION_TRIGGER_ANIMATION)) { | ||
176 | ExprEnabled = TRUE; | ||
177 | llRequestPermissions(avatar, PERMISSION_TRIGGER_ANIMATION); | ||
178 | } else { | ||
179 | stopAnim(); | ||
180 | llMessageLinked(LINK_SET, -11000, (string)BallNum + "|" + animation, avatar); | ||
181 | startAnim(animation); | ||
182 | } | ||
183 | } | ||
184 | |||
185 | run_time_permissions(integer perm) { | ||
186 | if (avatar != llGetPermissionsKey()) { | ||
187 | llWhisper(DEBUG_CHANNEL, "avatar != perm key"); | ||
188 | return; | ||
189 | } | ||
190 | |||
191 | if (perm & PERMISSION_TRIGGER_ANIMATION) { | ||
192 | stopAnim(); | ||
193 | llMessageLinked(LINK_SET, -11000, (string)BallNum + "|" + animation, avatar); | ||
194 | startAnim(animation); | ||
195 | } else { | ||
196 | llMessageLinked(LINK_SET, -11001, (string)BallNum, avatar); | ||
197 | llSetTimerEvent(0.0); | ||
198 | } | ||
199 | } | ||
200 | } | ||
diff --git a/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~poser 4.lsl b/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~poser 4.lsl new file mode 100644 index 0000000..fc976c4 --- /dev/null +++ b/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~poser 4.lsl | |||
@@ -0,0 +1,200 @@ | |||
1 | // MPLV2 2.3 by Learjeff Innis, based on | ||
2 | // MLP MULTI-LOVE-POSE V1.2 - Copyright (c) 2006, by Miffy Fluffy (BSD License) | ||
3 | // OpenSim port by Jez Ember | ||
4 | // Meta 7 fixes by onefang Rejected | ||
5 | |||
6 | integer ch; | ||
7 | string animation = "stand"; | ||
8 | key avatar; | ||
9 | |||
10 | integer ExprEnabled = TRUE; | ||
11 | string Expression; | ||
12 | float ExprTimer; | ||
13 | |||
14 | integer BallNum; | ||
15 | |||
16 | list Expressions = [ | ||
17 | "" | ||
18 | , "express_open_mouth" // 1 | ||
19 | , "express_surprise_emote" // 2 | ||
20 | , "express_tongue_out" // 3 | ||
21 | , "express_smile" // 4 | ||
22 | , "express_toothsmile" // 5 | ||
23 | , "express_wink_emote" // 6 | ||
24 | , "express_cry_emote" // 7 | ||
25 | , "express_kiss" // 8 | ||
26 | , "express_laugh_emote" // 9 | ||
27 | , "express_disdain" // 10 | ||
28 | , "express_repulsed_emote" // 11 | ||
29 | , "express_anger_emote" // 12 | ||
30 | , "express_bored_emote" // 13 | ||
31 | , "express_sad_emote" // 14 | ||
32 | , "express_embarrassed_emote" // 15 | ||
33 | , "express_frown" // 16 | ||
34 | , "express_shrug_emote" // 17 | ||
35 | , "express_afraid_emote" // 18 | ||
36 | , "express_worry_emote" // 19 | ||
37 | , "SLEEP" // 20 | ||
38 | ]; | ||
39 | |||
40 | |||
41 | stopAnim() { | ||
42 | key id = llGetPermissionsKey(); | ||
43 | list anims = llGetAnimationList(id); | ||
44 | integer ix; | ||
45 | for (ix = 0; ix < llGetListLength(anims); ++ix) { | ||
46 | string anim = llList2String(anims, ix); | ||
47 | if (anim != "") { | ||
48 | llStopAnimation(anim); | ||
49 | } | ||
50 | } | ||
51 | llSetTimerEvent(0.0); | ||
52 | } | ||
53 | |||
54 | startAnim(string anim) { | ||
55 | if (Expression != "") { | ||
56 | if (Expression == "SLEEP") { | ||
57 | llStartAnimation("express_disdain"); | ||
58 | llStartAnimation("express_smile"); | ||
59 | } else { | ||
60 | llStartAnimation(Expression); | ||
61 | } | ||
62 | if (ExprEnabled) { | ||
63 | llSetTimerEvent(ExprTimer); | ||
64 | } | ||
65 | } else { | ||
66 | stopAnim(); | ||
67 | } | ||
68 | if (anim != "") { | ||
69 | llStartAnimation(anim); | ||
70 | } | ||
71 | } | ||
72 | |||
73 | // Animation names with a "*" suffix get open mouth | ||
74 | // Those with a suffix of "::" followed by a number | ||
75 | // get the expression associated with that number. | ||
76 | // This can optionally be followed by another "::" delim, | ||
77 | // with a timer value following. | ||
78 | // Return the anim name without the suffix. | ||
79 | string getExpression(string anim) { | ||
80 | if (llGetSubString(anim,-1,-1) == "*") { | ||
81 | Expression = llList2String(Expressions, 1); | ||
82 | ExprTimer = 0.5; | ||
83 | return llGetSubString(anim, 0, -2); | ||
84 | } | ||
85 | integer ix = llSubStringIndex(anim, "::"); | ||
86 | if (ix == -1) { | ||
87 | Expression = ""; | ||
88 | ExprTimer = 0.5; | ||
89 | return anim; | ||
90 | } | ||
91 | |||
92 | list parms = llParseString2List(anim, ["::"], []); | ||
93 | anim = llList2String(parms, 0); | ||
94 | integer exprIx = (integer) llList2String(parms, 1); | ||
95 | Expression = llList2String(Expressions, exprIx); | ||
96 | ExprTimer = (float) llList2String(parms,2); | ||
97 | |||
98 | if (ExprTimer <= 0.0) { | ||
99 | ExprTimer = 0.5; | ||
100 | } | ||
101 | |||
102 | return anim; | ||
103 | } | ||
104 | |||
105 | getChan() { | ||
106 | BallNum = (integer) llGetSubString(llGetScriptName(),-1,-1); //offset from script name suffix | ||
107 | ch = BallNum | ||
108 | + (integer)("0x"+llGetSubString((string)llGetKey(),-4,-1)); //fixed channel for prim | ||
109 | } | ||
110 | |||
111 | default { | ||
112 | state_entry() { | ||
113 | state s_on; | ||
114 | } | ||
115 | } | ||
116 | |||
117 | state s_on { | ||
118 | state_entry() { | ||
119 | getChan(); | ||
120 | llListen(ch+8,"",NULL_KEY,""); | ||
121 | } | ||
122 | |||
123 | on_rez(integer arg) { | ||
124 | state default; | ||
125 | } | ||
126 | |||
127 | link_message(integer from, integer num, string an, key id) { //an animation is set | ||
128 | if (an == "PRIMTOUCH") { | ||
129 | return; | ||
130 | } | ||
131 | |||
132 | if (num != ch) return; | ||
133 | an = getExpression(an); // get & save expression, and return unadorned anim | ||
134 | |||
135 | if (avatar == llGetPermissionsKey() | ||
136 | && avatar != NULL_KEY | ||
137 | && animation != "") { | ||
138 | llStopAnimation(animation); | ||
139 | llMessageLinked(LINK_SET, -11002, (string)BallNum + "|" + an, avatar); | ||
140 | startAnim(an); | ||
141 | } | ||
142 | animation = an; | ||
143 | } | ||
144 | |||
145 | timer() { // timer to keep mouth open | ||
146 | if (Expression == "SLEEP") { | ||
147 | llStartAnimation("express_disdain"); | ||
148 | llStartAnimation("express_smile"); | ||
149 | } else if (Expression != "") { | ||
150 | llStartAnimation(Expression); | ||
151 | } | ||
152 | } | ||
153 | |||
154 | listen(integer channel, string name, key id, string str) { | ||
155 | if (str == "ALIVE" || str == "DIE") { | ||
156 | llMessageLinked(LINK_THIS,2,str,""); //send msg from ball to menu | ||
157 | if (str == "DIE") { | ||
158 | avatar = NULL_KEY; | ||
159 | llSetTimerEvent(0.0); | ||
160 | } | ||
161 | return; | ||
162 | } | ||
163 | |||
164 | avatar = (key) str; //avatar (sit) or NULL_KEY (stand up) | ||
165 | if (avatar == NULL_KEY) { | ||
166 | if (llGetPermissions() & PERMISSION_TRIGGER_ANIMATION) { | ||
167 | stopAnim(); | ||
168 | llMessageLinked(LINK_SET, -11001, (string)BallNum, llGetPermissionsKey()); | ||
169 | } | ||
170 | // llReleaseControls(); | ||
171 | return; | ||
172 | } | ||
173 | |||
174 | if (avatar != llGetPermissionsKey() | ||
175 | || ! (llGetPermissions() & PERMISSION_TRIGGER_ANIMATION)) { | ||
176 | ExprEnabled = TRUE; | ||
177 | llRequestPermissions(avatar, PERMISSION_TRIGGER_ANIMATION); | ||
178 | } else { | ||
179 | stopAnim(); | ||
180 | llMessageLinked(LINK_SET, -11000, (string)BallNum + "|" + animation, avatar); | ||
181 | startAnim(animation); | ||
182 | } | ||
183 | } | ||
184 | |||
185 | run_time_permissions(integer perm) { | ||
186 | if (avatar != llGetPermissionsKey()) { | ||
187 | llWhisper(DEBUG_CHANNEL, "avatar != perm key"); | ||
188 | return; | ||
189 | } | ||
190 | |||
191 | if (perm & PERMISSION_TRIGGER_ANIMATION) { | ||
192 | stopAnim(); | ||
193 | llMessageLinked(LINK_SET, -11000, (string)BallNum + "|" + animation, avatar); | ||
194 | startAnim(animation); | ||
195 | } else { | ||
196 | llMessageLinked(LINK_SET, -11001, (string)BallNum, avatar); | ||
197 | llSetTimerEvent(0.0); | ||
198 | } | ||
199 | } | ||
200 | } | ||
diff --git a/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~poser 5.lsl b/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~poser 5.lsl new file mode 100644 index 0000000..fc976c4 --- /dev/null +++ b/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~poser 5.lsl | |||
@@ -0,0 +1,200 @@ | |||
1 | // MPLV2 2.3 by Learjeff Innis, based on | ||
2 | // MLP MULTI-LOVE-POSE V1.2 - Copyright (c) 2006, by Miffy Fluffy (BSD License) | ||
3 | // OpenSim port by Jez Ember | ||
4 | // Meta 7 fixes by onefang Rejected | ||
5 | |||
6 | integer ch; | ||
7 | string animation = "stand"; | ||
8 | key avatar; | ||
9 | |||
10 | integer ExprEnabled = TRUE; | ||
11 | string Expression; | ||
12 | float ExprTimer; | ||
13 | |||
14 | integer BallNum; | ||
15 | |||
16 | list Expressions = [ | ||
17 | "" | ||
18 | , "express_open_mouth" // 1 | ||
19 | , "express_surprise_emote" // 2 | ||
20 | , "express_tongue_out" // 3 | ||
21 | , "express_smile" // 4 | ||
22 | , "express_toothsmile" // 5 | ||
23 | , "express_wink_emote" // 6 | ||
24 | , "express_cry_emote" // 7 | ||
25 | , "express_kiss" // 8 | ||
26 | , "express_laugh_emote" // 9 | ||
27 | , "express_disdain" // 10 | ||
28 | , "express_repulsed_emote" // 11 | ||
29 | , "express_anger_emote" // 12 | ||
30 | , "express_bored_emote" // 13 | ||
31 | , "express_sad_emote" // 14 | ||
32 | , "express_embarrassed_emote" // 15 | ||
33 | , "express_frown" // 16 | ||
34 | , "express_shrug_emote" // 17 | ||
35 | , "express_afraid_emote" // 18 | ||
36 | , "express_worry_emote" // 19 | ||
37 | , "SLEEP" // 20 | ||
38 | ]; | ||
39 | |||
40 | |||
41 | stopAnim() { | ||
42 | key id = llGetPermissionsKey(); | ||
43 | list anims = llGetAnimationList(id); | ||
44 | integer ix; | ||
45 | for (ix = 0; ix < llGetListLength(anims); ++ix) { | ||
46 | string anim = llList2String(anims, ix); | ||
47 | if (anim != "") { | ||
48 | llStopAnimation(anim); | ||
49 | } | ||
50 | } | ||
51 | llSetTimerEvent(0.0); | ||
52 | } | ||
53 | |||
54 | startAnim(string anim) { | ||
55 | if (Expression != "") { | ||
56 | if (Expression == "SLEEP") { | ||
57 | llStartAnimation("express_disdain"); | ||
58 | llStartAnimation("express_smile"); | ||
59 | } else { | ||
60 | llStartAnimation(Expression); | ||
61 | } | ||
62 | if (ExprEnabled) { | ||
63 | llSetTimerEvent(ExprTimer); | ||
64 | } | ||
65 | } else { | ||
66 | stopAnim(); | ||
67 | } | ||
68 | if (anim != "") { | ||
69 | llStartAnimation(anim); | ||
70 | } | ||
71 | } | ||
72 | |||
73 | // Animation names with a "*" suffix get open mouth | ||
74 | // Those with a suffix of "::" followed by a number | ||
75 | // get the expression associated with that number. | ||
76 | // This can optionally be followed by another "::" delim, | ||
77 | // with a timer value following. | ||
78 | // Return the anim name without the suffix. | ||
79 | string getExpression(string anim) { | ||
80 | if (llGetSubString(anim,-1,-1) == "*") { | ||
81 | Expression = llList2String(Expressions, 1); | ||
82 | ExprTimer = 0.5; | ||
83 | return llGetSubString(anim, 0, -2); | ||
84 | } | ||
85 | integer ix = llSubStringIndex(anim, "::"); | ||
86 | if (ix == -1) { | ||
87 | Expression = ""; | ||
88 | ExprTimer = 0.5; | ||
89 | return anim; | ||
90 | } | ||
91 | |||
92 | list parms = llParseString2List(anim, ["::"], []); | ||
93 | anim = llList2String(parms, 0); | ||
94 | integer exprIx = (integer) llList2String(parms, 1); | ||
95 | Expression = llList2String(Expressions, exprIx); | ||
96 | ExprTimer = (float) llList2String(parms,2); | ||
97 | |||
98 | if (ExprTimer <= 0.0) { | ||
99 | ExprTimer = 0.5; | ||
100 | } | ||
101 | |||
102 | return anim; | ||
103 | } | ||
104 | |||
105 | getChan() { | ||
106 | BallNum = (integer) llGetSubString(llGetScriptName(),-1,-1); //offset from script name suffix | ||
107 | ch = BallNum | ||
108 | + (integer)("0x"+llGetSubString((string)llGetKey(),-4,-1)); //fixed channel for prim | ||
109 | } | ||
110 | |||
111 | default { | ||
112 | state_entry() { | ||
113 | state s_on; | ||
114 | } | ||
115 | } | ||
116 | |||
117 | state s_on { | ||
118 | state_entry() { | ||
119 | getChan(); | ||
120 | llListen(ch+8,"",NULL_KEY,""); | ||
121 | } | ||
122 | |||
123 | on_rez(integer arg) { | ||
124 | state default; | ||
125 | } | ||
126 | |||
127 | link_message(integer from, integer num, string an, key id) { //an animation is set | ||
128 | if (an == "PRIMTOUCH") { | ||
129 | return; | ||
130 | } | ||
131 | |||
132 | if (num != ch) return; | ||
133 | an = getExpression(an); // get & save expression, and return unadorned anim | ||
134 | |||
135 | if (avatar == llGetPermissionsKey() | ||
136 | && avatar != NULL_KEY | ||
137 | && animation != "") { | ||
138 | llStopAnimation(animation); | ||
139 | llMessageLinked(LINK_SET, -11002, (string)BallNum + "|" + an, avatar); | ||
140 | startAnim(an); | ||
141 | } | ||
142 | animation = an; | ||
143 | } | ||
144 | |||
145 | timer() { // timer to keep mouth open | ||
146 | if (Expression == "SLEEP") { | ||
147 | llStartAnimation("express_disdain"); | ||
148 | llStartAnimation("express_smile"); | ||
149 | } else if (Expression != "") { | ||
150 | llStartAnimation(Expression); | ||
151 | } | ||
152 | } | ||
153 | |||
154 | listen(integer channel, string name, key id, string str) { | ||
155 | if (str == "ALIVE" || str == "DIE") { | ||
156 | llMessageLinked(LINK_THIS,2,str,""); //send msg from ball to menu | ||
157 | if (str == "DIE") { | ||
158 | avatar = NULL_KEY; | ||
159 | llSetTimerEvent(0.0); | ||
160 | } | ||
161 | return; | ||
162 | } | ||
163 | |||
164 | avatar = (key) str; //avatar (sit) or NULL_KEY (stand up) | ||
165 | if (avatar == NULL_KEY) { | ||
166 | if (llGetPermissions() & PERMISSION_TRIGGER_ANIMATION) { | ||
167 | stopAnim(); | ||
168 | llMessageLinked(LINK_SET, -11001, (string)BallNum, llGetPermissionsKey()); | ||
169 | } | ||
170 | // llReleaseControls(); | ||
171 | return; | ||
172 | } | ||
173 | |||
174 | if (avatar != llGetPermissionsKey() | ||
175 | || ! (llGetPermissions() & PERMISSION_TRIGGER_ANIMATION)) { | ||
176 | ExprEnabled = TRUE; | ||
177 | llRequestPermissions(avatar, PERMISSION_TRIGGER_ANIMATION); | ||
178 | } else { | ||
179 | stopAnim(); | ||
180 | llMessageLinked(LINK_SET, -11000, (string)BallNum + "|" + animation, avatar); | ||
181 | startAnim(animation); | ||
182 | } | ||
183 | } | ||
184 | |||
185 | run_time_permissions(integer perm) { | ||
186 | if (avatar != llGetPermissionsKey()) { | ||
187 | llWhisper(DEBUG_CHANNEL, "avatar != perm key"); | ||
188 | return; | ||
189 | } | ||
190 | |||
191 | if (perm & PERMISSION_TRIGGER_ANIMATION) { | ||
192 | stopAnim(); | ||
193 | llMessageLinked(LINK_SET, -11000, (string)BallNum + "|" + animation, avatar); | ||
194 | startAnim(animation); | ||
195 | } else { | ||
196 | llMessageLinked(LINK_SET, -11001, (string)BallNum, avatar); | ||
197 | llSetTimerEvent(0.0); | ||
198 | } | ||
199 | } | ||
200 | } | ||
diff --git a/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~poser.lsl b/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~poser.lsl new file mode 100644 index 0000000..fc976c4 --- /dev/null +++ b/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~poser.lsl | |||
@@ -0,0 +1,200 @@ | |||
1 | // MPLV2 2.3 by Learjeff Innis, based on | ||
2 | // MLP MULTI-LOVE-POSE V1.2 - Copyright (c) 2006, by Miffy Fluffy (BSD License) | ||
3 | // OpenSim port by Jez Ember | ||
4 | // Meta 7 fixes by onefang Rejected | ||
5 | |||
6 | integer ch; | ||
7 | string animation = "stand"; | ||
8 | key avatar; | ||
9 | |||
10 | integer ExprEnabled = TRUE; | ||
11 | string Expression; | ||
12 | float ExprTimer; | ||
13 | |||
14 | integer BallNum; | ||
15 | |||
16 | list Expressions = [ | ||
17 | "" | ||
18 | , "express_open_mouth" // 1 | ||
19 | , "express_surprise_emote" // 2 | ||
20 | , "express_tongue_out" // 3 | ||
21 | , "express_smile" // 4 | ||
22 | , "express_toothsmile" // 5 | ||
23 | , "express_wink_emote" // 6 | ||
24 | , "express_cry_emote" // 7 | ||
25 | , "express_kiss" // 8 | ||
26 | , "express_laugh_emote" // 9 | ||
27 | , "express_disdain" // 10 | ||
28 | , "express_repulsed_emote" // 11 | ||
29 | , "express_anger_emote" // 12 | ||
30 | , "express_bored_emote" // 13 | ||
31 | , "express_sad_emote" // 14 | ||
32 | , "express_embarrassed_emote" // 15 | ||
33 | , "express_frown" // 16 | ||
34 | , "express_shrug_emote" // 17 | ||
35 | , "express_afraid_emote" // 18 | ||
36 | , "express_worry_emote" // 19 | ||
37 | , "SLEEP" // 20 | ||
38 | ]; | ||
39 | |||
40 | |||
41 | stopAnim() { | ||
42 | key id = llGetPermissionsKey(); | ||
43 | list anims = llGetAnimationList(id); | ||
44 | integer ix; | ||
45 | for (ix = 0; ix < llGetListLength(anims); ++ix) { | ||
46 | string anim = llList2String(anims, ix); | ||
47 | if (anim != "") { | ||
48 | llStopAnimation(anim); | ||
49 | } | ||
50 | } | ||
51 | llSetTimerEvent(0.0); | ||
52 | } | ||
53 | |||
54 | startAnim(string anim) { | ||
55 | if (Expression != "") { | ||
56 | if (Expression == "SLEEP") { | ||
57 | llStartAnimation("express_disdain"); | ||
58 | llStartAnimation("express_smile"); | ||
59 | } else { | ||
60 | llStartAnimation(Expression); | ||
61 | } | ||
62 | if (ExprEnabled) { | ||
63 | llSetTimerEvent(ExprTimer); | ||
64 | } | ||
65 | } else { | ||
66 | stopAnim(); | ||
67 | } | ||
68 | if (anim != "") { | ||
69 | llStartAnimation(anim); | ||
70 | } | ||
71 | } | ||
72 | |||
73 | // Animation names with a "*" suffix get open mouth | ||
74 | // Those with a suffix of "::" followed by a number | ||
75 | // get the expression associated with that number. | ||
76 | // This can optionally be followed by another "::" delim, | ||
77 | // with a timer value following. | ||
78 | // Return the anim name without the suffix. | ||
79 | string getExpression(string anim) { | ||
80 | if (llGetSubString(anim,-1,-1) == "*") { | ||
81 | Expression = llList2String(Expressions, 1); | ||
82 | ExprTimer = 0.5; | ||
83 | return llGetSubString(anim, 0, -2); | ||
84 | } | ||
85 | integer ix = llSubStringIndex(anim, "::"); | ||
86 | if (ix == -1) { | ||
87 | Expression = ""; | ||
88 | ExprTimer = 0.5; | ||
89 | return anim; | ||
90 | } | ||
91 | |||
92 | list parms = llParseString2List(anim, ["::"], []); | ||
93 | anim = llList2String(parms, 0); | ||
94 | integer exprIx = (integer) llList2String(parms, 1); | ||
95 | Expression = llList2String(Expressions, exprIx); | ||
96 | ExprTimer = (float) llList2String(parms,2); | ||
97 | |||
98 | if (ExprTimer <= 0.0) { | ||
99 | ExprTimer = 0.5; | ||
100 | } | ||
101 | |||
102 | return anim; | ||
103 | } | ||
104 | |||
105 | getChan() { | ||
106 | BallNum = (integer) llGetSubString(llGetScriptName(),-1,-1); //offset from script name suffix | ||
107 | ch = BallNum | ||
108 | + (integer)("0x"+llGetSubString((string)llGetKey(),-4,-1)); //fixed channel for prim | ||
109 | } | ||
110 | |||
111 | default { | ||
112 | state_entry() { | ||
113 | state s_on; | ||
114 | } | ||
115 | } | ||
116 | |||
117 | state s_on { | ||
118 | state_entry() { | ||
119 | getChan(); | ||
120 | llListen(ch+8,"",NULL_KEY,""); | ||
121 | } | ||
122 | |||
123 | on_rez(integer arg) { | ||
124 | state default; | ||
125 | } | ||
126 | |||
127 | link_message(integer from, integer num, string an, key id) { //an animation is set | ||
128 | if (an == "PRIMTOUCH") { | ||
129 | return; | ||
130 | } | ||
131 | |||
132 | if (num != ch) return; | ||
133 | an = getExpression(an); // get & save expression, and return unadorned anim | ||
134 | |||
135 | if (avatar == llGetPermissionsKey() | ||
136 | && avatar != NULL_KEY | ||
137 | && animation != "") { | ||
138 | llStopAnimation(animation); | ||
139 | llMessageLinked(LINK_SET, -11002, (string)BallNum + "|" + an, avatar); | ||
140 | startAnim(an); | ||
141 | } | ||
142 | animation = an; | ||
143 | } | ||
144 | |||
145 | timer() { // timer to keep mouth open | ||
146 | if (Expression == "SLEEP") { | ||
147 | llStartAnimation("express_disdain"); | ||
148 | llStartAnimation("express_smile"); | ||
149 | } else if (Expression != "") { | ||
150 | llStartAnimation(Expression); | ||
151 | } | ||
152 | } | ||
153 | |||
154 | listen(integer channel, string name, key id, string str) { | ||
155 | if (str == "ALIVE" || str == "DIE") { | ||
156 | llMessageLinked(LINK_THIS,2,str,""); //send msg from ball to menu | ||
157 | if (str == "DIE") { | ||
158 | avatar = NULL_KEY; | ||
159 | llSetTimerEvent(0.0); | ||
160 | } | ||
161 | return; | ||
162 | } | ||
163 | |||
164 | avatar = (key) str; //avatar (sit) or NULL_KEY (stand up) | ||
165 | if (avatar == NULL_KEY) { | ||
166 | if (llGetPermissions() & PERMISSION_TRIGGER_ANIMATION) { | ||
167 | stopAnim(); | ||
168 | llMessageLinked(LINK_SET, -11001, (string)BallNum, llGetPermissionsKey()); | ||
169 | } | ||
170 | // llReleaseControls(); | ||
171 | return; | ||
172 | } | ||
173 | |||
174 | if (avatar != llGetPermissionsKey() | ||
175 | || ! (llGetPermissions() & PERMISSION_TRIGGER_ANIMATION)) { | ||
176 | ExprEnabled = TRUE; | ||
177 | llRequestPermissions(avatar, PERMISSION_TRIGGER_ANIMATION); | ||
178 | } else { | ||
179 | stopAnim(); | ||
180 | llMessageLinked(LINK_SET, -11000, (string)BallNum + "|" + animation, avatar); | ||
181 | startAnim(animation); | ||
182 | } | ||
183 | } | ||
184 | |||
185 | run_time_permissions(integer perm) { | ||
186 | if (avatar != llGetPermissionsKey()) { | ||
187 | llWhisper(DEBUG_CHANNEL, "avatar != perm key"); | ||
188 | return; | ||
189 | } | ||
190 | |||
191 | if (perm & PERMISSION_TRIGGER_ANIMATION) { | ||
192 | stopAnim(); | ||
193 | llMessageLinked(LINK_SET, -11000, (string)BallNum + "|" + animation, avatar); | ||
194 | startAnim(animation); | ||
195 | } else { | ||
196 | llMessageLinked(LINK_SET, -11001, (string)BallNum, avatar); | ||
197 | llSetTimerEvent(0.0); | ||
198 | } | ||
199 | } | ||
200 | } | ||
diff --git a/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~props.lsl b/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~props.lsl new file mode 100644 index 0000000..a731d77 --- /dev/null +++ b/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~props.lsl | |||
@@ -0,0 +1,397 @@ | |||
1 | //Imported by X-Avatar.de | ||
2 | //MPLV2 Version 2.3 by Learjeff Innis, based on | ||
3 | //MLP MULTI-LOVE-POSE V1.2 - Copyright (c) 2006, by Miffy Fluffy (BSD License) | ||
4 | |||
5 | |||
6 | // v2.2 - rotate all props | ||
7 | |||
8 | // This script handles props (object rezzed for a given pose) | ||
9 | |||
10 | integer Checking = FALSE; // whether doing consistency check | ||
11 | |||
12 | integer Line; | ||
13 | integer PoseCount; | ||
14 | list Poses; // name of each pose with a prop | ||
15 | list Positions; // position of prop, indexed as Poses | ||
16 | list Props; // name of each prop object, indexed as Poses | ||
17 | |||
18 | string Pose; // current pose name | ||
19 | |||
20 | integer ChatChan; // chan for talking to object | ||
21 | |||
22 | init() | ||
23 | { | ||
24 | ChatChan = - 1 - (integer)llFrand(-DEBUG_CHANNEL); | ||
25 | getRefPos(); | ||
26 | } | ||
27 | |||
28 | vector RefPos; | ||
29 | rotation RefRot; | ||
30 | |||
31 | getRefPos() { //reference position | ||
32 | RefPos = llGetPos(); | ||
33 | RefRot = llGetRot(); | ||
34 | integer z = (integer)llGetObjectDesc(); | ||
35 | RefPos.z += (float)z/100.0; | ||
36 | } | ||
37 | |||
38 | string plural(string singular, string plural, integer count) { | ||
39 | if (count != 1) { | ||
40 | return plural; | ||
41 | } | ||
42 | return singular; | ||
43 | } | ||
44 | |||
45 | announce() | ||
46 | { | ||
47 | llOwnerSay((string)PoseCount | ||
48 | + plural(" pose", " poses", PoseCount) | ||
49 | + " with props (" | ||
50 | + llGetScriptName() | ||
51 | + ": " | ||
52 | + (string)llGetFreeMemory() | ||
53 | + " bytes free)"); | ||
54 | } | ||
55 | |||
56 | string adjust(integer doOffset, vector pos, vector erot, vector amt) { | ||
57 | if (doOffset) { | ||
58 | pos += amt/100.; | ||
59 | return (vround(pos) + "/" + vround(erot)); | ||
60 | } | ||
61 | rotation amount = llEuler2Rot(amt * DEG_TO_RAD); | ||
62 | erot *= DEG_TO_RAD; | ||
63 | |||
64 | rotation oldrot = llEuler2Rot(erot); | ||
65 | rotation newrot = oldrot / amount; | ||
66 | |||
67 | erot = llRot2Euler(newrot) * RAD_TO_DEG; | ||
68 | pos = pos / amount; | ||
69 | return(vround(pos) + "/" + vround(erot)); | ||
70 | } | ||
71 | |||
72 | |||
73 | adjust_all(integer doOffset, vector amt) { | ||
74 | integer ix; | ||
75 | integer bx; | ||
76 | string data; | ||
77 | list ldata; | ||
78 | vector pos; | ||
79 | vector erot; | ||
80 | |||
81 | |||
82 | for (ix = 0; ix < llGetListLength(Poses); ++ix) { | ||
83 | data = llList2String(Positions, ix); | ||
84 | ldata = llParseString2List(data, ["/"], []); | ||
85 | pos = (vector)llList2String(ldata, 0); | ||
86 | erot = (vector)llList2String(ldata, 1); | ||
87 | |||
88 | data = adjust(doOffset, pos, erot, amt); | ||
89 | Positions = llListReplaceList(Positions, (list)data, ix, ix); | ||
90 | } | ||
91 | llOwnerSay("Prop rotation complete"); | ||
92 | } | ||
93 | |||
94 | |||
95 | |||
96 | string roundData(string data) { | ||
97 | list ldata = llParseString2List(data, ["/"], []); | ||
98 | return (vround((vector)llList2String(ldata, 0)) + "/" + vround((vector)llList2String(ldata, 1))); | ||
99 | } | ||
100 | |||
101 | // round a vector's components and return as vector value string | ||
102 | string vround(vector vec) { | ||
103 | return ("<"+round(vec.x, 3)+","+round(vec.y, 3)+","+round(vec.z, 3)+">"); | ||
104 | } | ||
105 | |||
106 | string round(float number, integer places) { | ||
107 | float shifted; | ||
108 | integer rounded; | ||
109 | string s; | ||
110 | shifted = number * llPow(10.0,(float)places); | ||
111 | rounded = llRound(shifted); | ||
112 | s = (string)((float)rounded / llPow(10.0,(float)places)); | ||
113 | s = llGetSubString(s,0,llSubStringIndex(s, ".")+places); | ||
114 | return s; | ||
115 | } | ||
116 | |||
117 | |||
118 | add_prop(string pose, string prop, string data) { | ||
119 | if (llListFindList(Props, (list)pose) != -1) { | ||
120 | llOwnerSay("Multiple *.PROPS* entries for pose '" + pose + "'"); | ||
121 | } | ||
122 | if (llGetInventoryType(prop) != INVENTORY_OBJECT) { | ||
123 | llOwnerSay("Warning: can't find prop '" + prop + "' in inventory"); | ||
124 | } | ||
125 | Poses = (list) pose; | ||
126 | Props = (list) prop; | ||
127 | Positions = (list) roundData(data); | ||
128 | ++PoseCount; | ||
129 | } | ||
130 | |||
131 | string get_pose_data(string pose) | ||
132 | { | ||
133 | integer ix = llListFindList(Poses, (list)pose); | ||
134 | |||
135 | if (ix == -1) { | ||
136 | return ""; | ||
137 | } | ||
138 | |||
139 | return llList2String(Positions, ix); | ||
140 | } | ||
141 | |||
142 | save_prop(string pose, string prop, string data) { | ||
143 | integer ix = llListFindList(Poses, [pose]); | ||
144 | if (ix == -1) { | ||
145 | // llSay(0, "new pose"); | ||
146 | add_prop(pose, prop, data); // don't expect this to happen | ||
147 | return; | ||
148 | } | ||
149 | |||
150 | // if the prop object name doesn't match, ignore it -- assume it's noise | ||
151 | if (llList2String(Props, ix) != prop) { | ||
152 | return; | ||
153 | } | ||
154 | |||
155 | // Data is the change in position since we rezzed it, in global coords | ||
156 | // Convert delta to local axes | ||
157 | |||
158 | list ldata = llParseString2List(data, ["/"], []); | ||
159 | vector pos = (vector) llList2String(ldata, 0); | ||
160 | rotation rot = (rotation)llList2String(ldata, 1); | ||
161 | |||
162 | pos = pos / RefRot; | ||
163 | vector erot = llRot2Euler(rot/RefRot) * RAD_TO_DEG; | ||
164 | |||
165 | // Now add to saved data (since it was a delta) | ||
166 | ldata = llParseStringKeepNulls(llList2String(Positions, ix), ["/"], []); | ||
167 | vector oldpos = (vector)llList2String(ldata, 0); | ||
168 | |||
169 | pos += oldpos; | ||
170 | data = vround(pos) + "/" + vround(erot); | ||
171 | |||
172 | Props = llListReplaceList(Props, (list)prop, ix, ix); | ||
173 | Positions = llListReplaceList(Positions, (list)data, ix, ix); | ||
174 | |||
175 | string name = llGetObjectName(); | ||
176 | llSetObjectName(""); | ||
177 | llOwnerSay("| " + pose + " | " + prop + " | " + data); | ||
178 | llSetObjectName(name); | ||
179 | } | ||
180 | |||
181 | rez_prop(string pose) { | ||
182 | llSay(ChatChan, "DIE"); | ||
183 | integer ix = -1; //(integer)llListFindList(Poses, [pose]); | ||
184 | integer ggt =0; | ||
185 | for (ggt=0; ggt < llGetListLength(Poses); ggt++) | ||
186 | { | ||
187 | if (llList2String(Poses,ggt) == pose) | ||
188 | { | ||
189 | ix = ggt; | ||
190 | ggt = llGetListLength(Poses); | ||
191 | } | ||
192 | } | ||
193 | if (ix == -1) | ||
194 | { | ||
195 | Pose = ""; | ||
196 | llSetTimerEvent(0.0); | ||
197 | return; | ||
198 | } | ||
199 | string prop = llList2String(Props, ix); | ||
200 | string data = llList2String(Positions, ix); | ||
201 | list ldata = llParseString2List(data, ["/"], []); | ||
202 | vector pos = (vector)llList2String(ldata, 0); | ||
203 | vector erot = (vector)llList2String(ldata, 1); | ||
204 | |||
205 | pos = pos * RefRot + RefPos; | ||
206 | rotation rot = llEuler2Rot(erot*DEG_TO_RAD) * RefRot; | ||
207 | |||
208 | // llSay(0, "rezzing '" + prop + "' at " + (string) pos); | ||
209 | llRezAtRoot(prop, pos, <0.,0.,0.>, rot, ChatChan); | ||
210 | llSetTimerEvent(60.0); | ||
211 | Pose = pose; | ||
212 | } | ||
213 | |||
214 | |||
215 | dashes() { | ||
216 | llOwnerSay("_______________________________________________________________________________"); | ||
217 | llOwnerSay(""); | ||
218 | } | ||
219 | |||
220 | |||
221 | // Globals for reading card config | ||
222 | integer ConfigLineIndex; | ||
223 | list ConfigCards; // list of names of config cards | ||
224 | string ConfigCardName; // name of card being read | ||
225 | integer ConfigCardIndex; // index of next card to read | ||
226 | key ConfigQueryId; | ||
227 | |||
228 | integer next_card() | ||
229 | { | ||
230 | if (ConfigCardIndex >= llGetListLength(ConfigCards)) { | ||
231 | ConfigCards = []; | ||
232 | return (FALSE); | ||
233 | } | ||
234 | |||
235 | ConfigLineIndex = 0; | ||
236 | ConfigCardName = llList2String(ConfigCards, ConfigCardIndex); | ||
237 | ConfigCardIndex++; | ||
238 | ConfigQueryId = llGetNotecardLine(ConfigCardName, ConfigLineIndex); | ||
239 | llOwnerSay("Reading " + ConfigCardName); | ||
240 | return (TRUE); | ||
241 | } | ||
242 | |||
243 | |||
244 | default { | ||
245 | state_entry() { | ||
246 | llSleep(0.25); // give ~run a chance to shut us down | ||
247 | string item; | ||
248 | ConfigCards = []; | ||
249 | integer n = llGetInventoryNumber(INVENTORY_NOTECARD); | ||
250 | while (n-- > 0) { | ||
251 | item = llGetInventoryName(INVENTORY_NOTECARD, n); | ||
252 | if (llSubStringIndex(item, ".PROPS") != -1) { | ||
253 | ConfigCards = (list) item; | ||
254 | } | ||
255 | } | ||
256 | |||
257 | ConfigCardIndex = 0; | ||
258 | ConfigCards = llListSort(ConfigCards, 1, TRUE); | ||
259 | next_card(); | ||
260 | } | ||
261 | |||
262 | dataserver(key query_id, string data2) { | ||
263 | if (query_id != ConfigQueryId) { | ||
264 | return; | ||
265 | } | ||
266 | if (data2 == EOF) { | ||
267 | if (next_card()) { | ||
268 | return; | ||
269 | } | ||
270 | state on; | ||
271 | } | ||
272 | |||
273 | string data3 = llStringTrim(data2, STRING_TRIM); | ||
274 | if (llGetSubString(data3,0,0) != "/" && llStringLength(data3)) { // skip comments and blank lines | ||
275 | |||
276 | list ldata = llParseStringKeepNulls(data3, [" | "," | "," | "," | "," |","| ","|"], []); | ||
277 | if (llGetListLength(ldata) != 4) { | ||
278 | llOwnerSay(llGetScriptName() + ": error in " + ConfigCardName + ":" + (string)ConfigLineIndex | ||
279 | + " - need exactly 3 vertical bars - line ignored"); | ||
280 | } else { | ||
281 | string pose = llList2String(ldata, 1); | ||
282 | string prop = llList2String(ldata, 2); | ||
283 | string data = llStringTrim(llList2String(ldata, 3), STRING_TRIM); | ||
284 | if (data3 == "") { | ||
285 | data3 = "<0,0,1>/<0,0,0>"; | ||
286 | } | ||
287 | add_prop(pose, prop, data3); | ||
288 | } | ||
289 | } | ||
290 | ++ConfigLineIndex; | ||
291 | ConfigQueryId = llGetNotecardLine(ConfigCardName, ConfigLineIndex); //read next line of positions notecard | ||
292 | } | ||
293 | |||
294 | state_exit() { | ||
295 | // do one save to indicate actual amount of available memory | ||
296 | string position = llList2String(Positions, 0); | ||
297 | Positions = llListReplaceList(Positions, [position],0,0); | ||
298 | |||
299 | llMessageLinked(LINK_THIS, 2, "OK", (key)""); //msg to menu, in case it's waiting for loading | ||
300 | announce(); | ||
301 | } | ||
302 | } | ||
303 | |||
304 | state re_on | ||
305 | { | ||
306 | state_entry() { | ||
307 | state on; | ||
308 | } | ||
309 | } | ||
310 | |||
311 | state on { | ||
312 | state_entry() { | ||
313 | init(); | ||
314 | llListen(ChatChan, "", NULL_KEY, ""); | ||
315 | } | ||
316 | |||
317 | on_rez(integer arg) { | ||
318 | state re_on; | ||
319 | } | ||
320 | |||
321 | listen(integer chan, string name, key id, string msg) { | ||
322 | // llSay(0, name + ": " + msg); | ||
323 | if (Pose == "") { | ||
324 | return; | ||
325 | } | ||
326 | save_prop(Pose, name, msg); | ||
327 | announce(); | ||
328 | } | ||
329 | |||
330 | link_message(integer from, integer num, string str, key dkey) { | ||
331 | |||
332 | if (str == "PRIMTOUCH" || num < 0) { | ||
333 | return; | ||
334 | } | ||
335 | |||
336 | if (num == 0) { | ||
337 | if (str == "POSEB") { | ||
338 | rez_prop((string)dkey); | ||
339 | return; | ||
340 | } | ||
341 | if (str == "REPOS") { | ||
342 | getRefPos(); | ||
343 | return; | ||
344 | } | ||
345 | return; | ||
346 | } | ||
347 | |||
348 | if (num != 1) { | ||
349 | return; | ||
350 | } | ||
351 | |||
352 | if (str == "STOP") { | ||
353 | llSay(ChatChan, "DIE"); | ||
354 | Pose = ""; | ||
355 | llSetTimerEvent(0.0); | ||
356 | } | ||
357 | |||
358 | if (str == "DUMPPROPS") { | ||
359 | dashes(); | ||
360 | llOwnerSay("Copy to .PROPS; delete any other *.PROPS* cards"); | ||
361 | dashes(); | ||
362 | string name = llGetObjectName(); | ||
363 | llSetObjectName(""); | ||
364 | |||
365 | integer ix; | ||
366 | for (ix = 0; ix < PoseCount; ++ix) { | ||
367 | string pose = llList2String(Poses, ix); | ||
368 | string prop = llList2String(Props, ix); | ||
369 | llOwnerSay("| " + pose + " | " + prop + " | " + get_pose_data(pose)); | ||
370 | } | ||
371 | llSetObjectName(name); | ||
372 | dashes(); | ||
373 | } else if (llSubStringIndex(str, "REORIENT=") == 0) { | ||
374 | // Reorient command (LINKMENU command from .MENUITEMS file) | ||
375 | // str format: REORIENT=OFF=<x,y,z> or REORIENT=ROT=<x,y,z> (in degrees) | ||
376 | list parms = llParseString2List(str, ["="], []); | ||
377 | vector amount = (vector)llList2String(parms, 2); | ||
378 | llWhisper(0, "Adjusting props, please wait"); | ||
379 | |||
380 | if (llList2String(parms, 1) == "OFF") { | ||
381 | adjust_all(TRUE, amount); | ||
382 | } else { | ||
383 | adjust_all(FALSE, amount); | ||
384 | } | ||
385 | llMessageLinked(LINK_THIS, 0, "AGAIN", (key)""); | ||
386 | llWhisper(0, "Prop adjustment complete"); | ||
387 | } else if (str == "SAVEPROP") { | ||
388 | llSay(ChatChan, "SAVE"); | ||
389 | } | ||
390 | } | ||
391 | |||
392 | timer() { | ||
393 | llSay(ChatChan, "LIVE"); | ||
394 | } | ||
395 | |||
396 | } | ||
397 | |||
diff --git a/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~run.lsl b/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~run.lsl new file mode 100644 index 0000000..2d56983 --- /dev/null +++ b/media/Test sim/objects/onefang%27s%20test%20bed.5cb927d5-1304-4f1a-9947-308251ef2df0/~run.lsl | |||
@@ -0,0 +1,194 @@ | |||
1 | //MLPV2 Version 2.3 - Learjeff Innis, from | ||
2 | //MLP MULTI-LOVE-POSE V1.2 - Copyright (c) 2006, by Miffy Fluffy (BSD License) | ||
3 | //To donate, go to my profile (Search - People - Miffy Fluffy) and use the "Pay..." button, thanks! | ||
4 | //You can also find the link to the latest version here. | ||
5 | // OpenSim port by Jez Ember | ||
6 | // Meta 7 fixes by onefang Rejected | ||
7 | |||
8 | integer MAX_AVS = 6; | ||
9 | integer ResetOnOwnerChange = FALSE; | ||
10 | |||
11 | // DESCRIPTION OF THE SCRIPTS | ||
12 | // | ||
13 | // ~run: | ||
14 | // Default: sets other scripts to not running. | ||
15 | // When the object is touched it will start all scrips. | ||
16 | // | ||
17 | // ~memory: | ||
18 | // Here the positions are stored permanently. Information is still kept when the script is | ||
19 | // not running or when everything is placed in inventory. The information will be lost only | ||
20 | // when the ~memory script is reset. | ||
21 | // A backup can be made on the .POSITIONS notecard, when the memory is empty, it will start | ||
22 | // reading the .POSITIONS notecard automatically. | ||
23 | // | ||
24 | // ~menu: | ||
25 | // 1.loading: reads the .MENUITEMS notecard and builds the menu. | ||
26 | // When it reads a "POSE": - the animations are stored in ~pose | ||
27 | // - their matching positions are looked up in ~memory and stored | ||
28 | // in ~pos. | ||
29 | // 2.ready: | ||
30 | // When the object is touched: - shows the main menu | ||
31 | // - listens for menu selections. | ||
32 | // | ||
33 | // When a submenu is selected: - shows the submenu | ||
34 | // - when balls are defined for this submenu it will rez | ||
35 | // balls (if not already there) and set their colors. | ||
36 | // | ||
37 | // When a pose is selected: - ~pose will send the animations to ~pose1 and ~pose2, | ||
38 | // they will set the animations to the avatars | ||
39 | // - ~pos wil send the matching positions to each ball. | ||
40 | // | ||
41 | // When a position is saved: - ~pose will ask the balls for their position | ||
42 | // - the positions are saved in ~memory ("permanent") | ||
43 | // - the positions are updated in ~pos | ||
44 | // | ||
45 | // When "STOP" is selected: - will hide the balls | ||
46 | // - will stop the pose | ||
47 | // When "STOP" is selected again (or if no pose is started yet): | ||
48 | // - will remove the balls (derez/die) | ||
49 | // | ||
50 | // ~pos: | ||
51 | // - loads the positions from ~memory and stores them (until shutdown/restart) | ||
52 | // - sends positions for the selected pose to the balls | ||
53 | // | ||
54 | // ~pose: | ||
55 | // - loads the animations from the .MENUITEMS notecard and stores them (until shutdown/restart) | ||
56 | // - sends animations for the selected pose to ~pose1 and ~pose2 | ||
57 | // - when saving a position: will ask balls for their position and sends it to ~pos and ~memory | ||
58 | // (~pos would be a more logical place to handle this, but ~pose has more free memory). | ||
59 | // | ||
60 | // ~poser, ~poser 1, ~poser 2, ~poser 3 (one for each ball): | ||
61 | // - will ask permission to animate the avatar on ball | ||
62 | // - will set the animations to avatar | ||
63 | // | ||
64 | // ~ball | ||
65 | // - when balls are defined for a submenu (in .MENUITEMS), ~menu will rez copies of ~ball | ||
66 | // - each will receive a unique communication channel from ~menu | ||
67 | // - the color for each ball is set by ~menu | ||
68 | // - the position of each ball is set by ~pos | ||
69 | // - when an avatar selects to sit on a ball, the avatar info is sent to the appropriate; they | ||
70 | // will ask permission and set the animation directly to the avatar (not via the ball) | ||
71 | // - balls will commit suicide when they don't hear a "LIVE" message each minute (from ~menu). | ||
72 | // | ||
73 | // have fun! | ||
74 | |||
75 | //Note: if you make a revised version, please mention something like this: | ||
76 | //"MLP - alternative version by ... .... - Revision 1 (based on MLP V1.2 by Miffy Fluffy) | ||
77 | |||
78 | key Owner; | ||
79 | |||
80 | list Scripts = [ | ||
81 | "~menucfg" | ||
82 | , "~pos" | ||
83 | , "~pose" | ||
84 | , "~poser" | ||
85 | , "~poser 1" | ||
86 | , "~poser 2" | ||
87 | , "~poser 3" | ||
88 | , "~poser 4" | ||
89 | , "~poser 5" | ||
90 | ]; | ||
91 | |||
92 | list OptionalScripts = [ | ||
93 | "~props" | ||
94 | , "~sequencer" | ||
95 | ]; | ||
96 | |||
97 | setRunning(integer st) { | ||
98 | integer ix; | ||
99 | list scripts = Scripts; | ||
100 | string script; | ||
101 | |||
102 | for (ix = 0; ix < 100; ++ix) { | ||
103 | integer jx; | ||
104 | |||
105 | // try to stop any remaining scripts in the list | ||
106 | for (jx = llGetListLength(scripts) - 1; jx >= 0; --jx) { | ||
107 | script = llList2String(scripts, jx); | ||
108 | if (llGetInventoryType(script) == INVENTORY_SCRIPT) { | ||
109 | llSetScriptState(script, st); | ||
110 | scripts = llDeleteSubList(scripts, jx, jx); | ||
111 | --jx; | ||
112 | } | ||
113 | } | ||
114 | |||
115 | // got them all yet? | ||
116 | if (llGetListLength(scripts) == 0) { | ||
117 | // Yes -- handle key ones | ||
118 | llSetScriptState("~memory", st); | ||
119 | llSetScriptState("~menu", st); | ||
120 | if (st) { | ||
121 | llResetOtherScript("~memory"); | ||
122 | llResetOtherScript("~menu"); | ||
123 | } | ||
124 | |||
125 | // start/stop optional scripts if present | ||
126 | for (jx = llGetListLength(OptionalScripts) - 1; jx >= 0; --jx) { | ||
127 | script = llList2String(OptionalScripts, jx); | ||
128 | if (llGetInventoryType(script) == INVENTORY_SCRIPT) { | ||
129 | llSetScriptState(script, st); | ||
130 | } | ||
131 | } | ||
132 | return; | ||
133 | } | ||
134 | |||
135 | llSleep(0.1); | ||
136 | } | ||
137 | |||
138 | llOwnerSay("missing scripts: " + llList2CSV(scripts)); | ||
139 | } | ||
140 | |||
141 | setBalls(string cmd) { | ||
142 | integer ch = channel(); | ||
143 | integer ix; | ||
144 | |||
145 | for (ix = 0; ix < MAX_AVS; ++ix) { | ||
146 | llSay(ch + ix, cmd); //msg to balls | ||
147 | } | ||
148 | } | ||
149 | |||
150 | integer channel() { | ||
151 | return (integer)("0x"+llGetSubString((string)llGetKey(),-4,-1)); | ||
152 | } | ||
153 | |||
154 | default { | ||
155 | |||
156 | state_entry() { | ||
157 | setBalls("DIE"); | ||
158 | Owner = llGetOwner(); | ||
159 | setRunning(FALSE); | ||
160 | llOwnerSay("OFF (touch to switch on)"); | ||
161 | } | ||
162 | |||
163 | touch_start(integer i) { | ||
164 | llOwnerSay("SOMEONE TOUCHED ME!!!!"); | ||
165 | if (llDetectedKey(0) == llGetOwner()) state run; | ||
166 | } | ||
167 | |||
168 | // Waits for another script to send a link message. | ||
169 | link_message(integer sender_num, integer num, string str, key id) { | ||
170 | if (str == "PRIMTOUCH" && id == llGetOwner()) { | ||
171 | state run; | ||
172 | } | ||
173 | } | ||
174 | |||
175 | changed(integer change) { | ||
176 | if (change & CHANGED_OWNER && Owner != llGetOwner()) { | ||
177 | llResetScript(); | ||
178 | } | ||
179 | } | ||
180 | } | ||
181 | |||
182 | state run { | ||
183 | state_entry() { | ||
184 | llOwnerSay("RUNNING NOW."); | ||
185 | setRunning(TRUE); | ||
186 | } | ||
187 | changed(integer change) { | ||
188 | if (ResetOnOwnerChange | ||
189 | && (change & CHANGED_OWNER) | ||
190 | && Owner != llGetOwner()) { | ||
191 | llResetScript(); | ||
192 | } | ||
193 | } | ||
194 | } | ||
diff --git a/media/Test sim/objects/test.lsl b/media/Test sim/objects/test.lsl new file mode 100644 index 0000000..6e1d915 --- /dev/null +++ b/media/Test sim/objects/test.lsl | |||
@@ -0,0 +1,14 @@ | |||
1 | |||
2 | default | ||
3 | { | ||
4 | state_entry() | ||
5 | { | ||
6 | llSay(0, /* */ 4 /* c */ + /* c0 */ 2 /* c1 */ * /* c2 */ 10 /* c3 */ + /* c4 */ | ||
7 | 3 /* c5 */ * /* c6 */ ( /* c7 */ 5 /* c8 */ + /* c9 */ 1 /* cA */ ) /* cB */) ; /* cE */ | ||
8 | // Some more arithmetic - | ||
9 | llSay(0, 1+1); | ||
10 | llSay(0, 20.5 + 20 + 1.5); | ||
11 | } | ||
12 | } | ||
13 | |||
14 | // This is the end my friend. \ No newline at end of file | ||