|
| 1 | +/* |
| 2 | +The nPose scripts are licensed under the GPLv2 (http://www.gnu.org/licenses/gpl-2.0.txt), with the following addendum: |
| 3 | +
|
| 4 | +The nPose scripts are free to be copied, modified, and redistributed, subject to the following conditions: |
| 5 | + - If you distribute the nPose scripts, you must leave them full perms. |
| 6 | + - If you modify the nPose scripts and distribute the modifications, you must also make your modifications full perms. |
| 7 | +
|
| 8 | +"Full perms" means having the modify, copy, and transfer permissions enabled in Second Life and/or other virtual world platforms derived from Second Life (such as OpenSim). If the platform should allow more fine-grained permissions, then "full perms" will mean the most permissive possible set of permissions allowed by the platform. |
| 9 | +*/ |
| 10 | +integer LAYER_POSE = -218; |
| 11 | +list AnimsList; //[string command, string animation name] use a list to layer multiple animations. |
| 12 | +list Lastanim; |
| 13 | +integer Primcount; |
| 14 | +integer Newprimcount; |
| 15 | +list Faceanims; |
| 16 | +integer GotFaceAnim = 0; |
| 17 | +integer Seatcount; |
| 18 | + |
| 19 | +integer OPTIONS = -240; |
| 20 | +integer SEAT_UPDATE = 35353; |
| 21 | +integer MENU_USAGE = 34334; |
| 22 | +list FaceTimes = []; |
| 23 | +list Slots; |
| 24 | +key ThisAV; |
| 25 | +integer Stop; |
| 26 | +integer FACIALS_FLAG = -241; |
| 27 | +integer FacialEnable = 1; |
| 28 | + |
| 29 | + |
| 30 | + |
| 31 | +list SeatedAvs() { |
| 32 | + list avs = []; |
| 33 | + integer n = llGetNumberOfPrims(); |
| 34 | + for(; n >= llGetObjectPrimCount(llGetKey()); --n) { |
| 35 | + key id = llGetLinkKey(n); |
| 36 | + if(llGetAgentSize(id) != ZERO_VECTOR) { |
| 37 | + avs = [id] + avs; |
| 38 | + } |
| 39 | + } |
| 40 | + return avs; |
| 41 | +} |
| 42 | + |
| 43 | +doSeats(integer slotNum, key avKey) { |
| 44 | + llSetTimerEvent(0.0); |
| 45 | + if(avKey != "") { |
| 46 | + Stop = llGetListLength(Slots)/8; |
| 47 | + llRequestPermissions(avKey, PERMISSION_TRIGGER_ANIMATION); |
| 48 | + } |
| 49 | +} |
| 50 | + |
| 51 | +integer AvLinkNum(key av) { |
| 52 | + integer linkcount = llGetNumberOfPrims(); |
| 53 | + while(av != llGetLinkKey(linkcount)) { |
| 54 | + if(llGetAgentSize(llGetLinkKey(linkcount)) == ZERO_VECTOR) { |
| 55 | + return -1; |
| 56 | + } |
| 57 | + linkcount--; |
| 58 | + } |
| 59 | + return linkcount; |
| 60 | +} |
| 61 | + |
| 62 | +default { |
| 63 | + state_entry() { |
| 64 | + Primcount = llGetNumberOfPrims(); |
| 65 | + Newprimcount = Primcount; |
| 66 | + } |
| 67 | + |
| 68 | + link_message(integer sender, integer num, string str, key id) { |
| 69 | + if(num == LAYER_POSE) { |
| 70 | + key av; |
| 71 | + list tempList = llParseString2List(str, ["/"], []); |
| 72 | + if(llListFindList(SeatedAvs(), [(key)llList2String(tempList, 0)]) != -1) { |
| 73 | + av = (key)llList2String(tempList, 0); |
| 74 | + } |
| 75 | + if(av) { |
| 76 | + llRequestPermissions(av, PERMISSION_TRIGGER_ANIMATION); |
| 77 | + av = llGetPermissionsKey(); |
| 78 | + list tempList1 = llParseString2List(llList2String(tempList, 1), ["~"], []); |
| 79 | + integer instruction; |
| 80 | + integer layerStop = llGetListLength(tempList1); |
| 81 | + for(instruction = 0; instruction < layerStop; ++instruction) { |
| 82 | + tempList = llParseString2List(llList2String(tempList1, instruction), [","],[]); |
| 83 | + if(llList2String(tempList,0)=="stopAll") { |
| 84 | + AnimsList = [av, llList2String(tempList, 0), llList2String(tempList, 1)] + AnimsList; |
| 85 | + } |
| 86 | + else { |
| 87 | + integer index = llListFindList(AnimsList, [llList2String(tempList, 1)]); |
| 88 | + if(index>=1 & (key)llList2String(AnimsList, index - 2) == av) { |
| 89 | + AnimsList = llDeleteSubList(AnimsList, index-2, index); |
| 90 | + } |
| 91 | + AnimsList += [av, llList2String(tempList, 0), llList2String(tempList, 1)]; |
| 92 | + } |
| 93 | + } |
| 94 | + integer n; |
| 95 | + layerStop = llGetListLength(AnimsList)/3; |
| 96 | + for(n=0; n<layerStop; ++n) { |
| 97 | + if((key)llList2String(AnimsList, n*3) == av) { |
| 98 | + if(llList2String(AnimsList, n*3+1) == "stopAll") { |
| 99 | + AnimsList = llDeleteSubList(AnimsList, n*3, n*3+2); |
| 100 | + n-=1; |
| 101 | + layerStop-=1; |
| 102 | + integer x; |
| 103 | + integer animsStop = llGetListLength(AnimsList)/3; |
| 104 | + if(animsStop > 0) { |
| 105 | + for(x = 0; x<animsStop; ++x) { |
| 106 | + if ((key)llList2String(AnimsList, x*3) == av && llList2String(AnimsList, x*3+2) != ""){ |
| 107 | + llStopAnimation(llList2String(AnimsList, x*3+2)); |
| 108 | + AnimsList = llDeleteSubList(AnimsList, x*3, x*3+2); |
| 109 | + x-=1; |
| 110 | + animsStop-=1; |
| 111 | + } |
| 112 | + } |
| 113 | + } |
| 114 | + } |
| 115 | + else if(llList2String(AnimsList, n*3+1) == "start" && llList2String(AnimsList, n*3) == av |
| 116 | + && llList2String(AnimsList, n*3+2) != "") { |
| 117 | + if(llGetPermissions() & PERMISSION_TRIGGER_ANIMATION) { |
| 118 | + llStartAnimation(llList2String(AnimsList, n*3+2)); |
| 119 | + } |
| 120 | + } |
| 121 | + else if(llList2String(AnimsList, n*3+1) == "stop") { |
| 122 | + if (llGetPermissions() & PERMISSION_TRIGGER_ANIMATION){ |
| 123 | + llStopAnimation(llList2String(AnimsList, n*3+2)); |
| 124 | + AnimsList = llDeleteSubList(AnimsList, n*3, n*3+2); |
| 125 | + n-=1; |
| 126 | + layerStop-=1; |
| 127 | + } |
| 128 | + } |
| 129 | + } |
| 130 | + } |
| 131 | + } |
| 132 | +// llSay(0, "anim list:\n" + llList2CSV(llGetAnimationList(av))); |
| 133 | + } |
| 134 | + else if(num == SEAT_UPDATE){ |
| 135 | + list seatsavailable = llParseStringKeepNulls(str, ["^"], []); |
| 136 | + str = ""; |
| 137 | + integer stop = llGetListLength(seatsavailable)/8; |
| 138 | + Slots = []; |
| 139 | + FaceTimes = []; |
| 140 | + GotFaceAnim = 0; |
| 141 | + for(Seatcount = 1; Seatcount <= stop; ++Seatcount) { |
| 142 | + Slots = Slots + [llList2String(seatsavailable, (Seatcount-1)*8), (vector)llList2String(seatsavailable, (Seatcount-1)*8+1), |
| 143 | + (rotation)llList2String(seatsavailable, (Seatcount-1)*8+2), llList2String(seatsavailable, (Seatcount-1)*8+3), |
| 144 | + (key)llList2String(seatsavailable, (Seatcount-1)*8+4), llList2String(seatsavailable, (Seatcount-1)*8+5), |
| 145 | + llList2String(seatsavailable, (Seatcount-1)*8+6), llList2String(seatsavailable, (Seatcount-1)*8+7)]; |
| 146 | + if(llList2String(seatsavailable, (Seatcount-1)*8+3) != "") { |
| 147 | + //we need a list consisting of sitter key followed by each face anim and the associated time of each |
| 148 | + //put face anims for this slot in a list |
| 149 | + list faceanimsTemp = llParseString2List(llList2String(seatsavailable, (Seatcount-1)*8+3), ["~"], []); |
| 150 | + integer facecount = llGetListLength(faceanimsTemp); |
| 151 | + list faces = []; |
| 152 | + integer nFace; |
| 153 | + integer hasNewFaceTime = 0; |
| 154 | + for(nFace=0; nFace<facecount; ++nFace) { |
| 155 | + //parse this face anim for anim name and time |
| 156 | + list temp = llParseString2List(llList2String(faceanimsTemp, nFace), ["="], []); |
| 157 | + //time must be optional so we will make default a zero |
| 158 | + //queue on zero to revert to older stuff |
| 159 | + if(llList2String(temp, 1)) { |
| 160 | + //collect the name of the anim and the time |
| 161 | + faces += [llList2String(temp, 0), (integer)llList2String(temp, 1)]; |
| 162 | + hasNewFaceTime = 1; |
| 163 | + } |
| 164 | + else { |
| 165 | + faces += [llList2String(temp, 0), -1]; |
| 166 | + } |
| 167 | + } |
| 168 | + GotFaceAnim=1; |
| 169 | + //add sitter key and flag if timer defined followed by a stride 2 list containing face anim name and associated time |
| 170 | + FaceTimes += [(key)llList2String(seatsavailable, (Seatcount-1)*8+4), hasNewFaceTime, facecount] + faces; |
| 171 | + } |
| 172 | + } |
| 173 | + //we have our new list of AV's and positions so put them where they belong. fire off the first seated AV and run time will do the rest. |
| 174 | + for(Seatcount = 0; Seatcount < stop; ++Seatcount) { |
| 175 | + if(llList2Key(Slots, Seatcount*8+4) != "") { |
| 176 | + if(llListFindList(SeatedAvs(), [llList2Key(Slots, Seatcount*8+4)]) != -1) { |
| 177 | + doSeats(Seatcount, llList2String(Slots, (Seatcount)*8+4)); |
| 178 | + return; |
| 179 | + } |
| 180 | + } |
| 181 | + } |
| 182 | + } |
| 183 | + else if(num == OPTIONS) { |
| 184 | + //save new option(s) from LINKMSG |
| 185 | + list optionsToSet = llParseStringKeepNulls(str, ["~","|"], []); |
| 186 | + integer length = llGetListLength(optionsToSet); |
| 187 | + integer index; |
| 188 | + for(; index<length; ++index) { |
| 189 | + list optionsItems = llParseString2List(llList2String(optionsToSet, index), ["="], []); |
| 190 | + string optionItem = llToLower(llStringTrim(llList2String(optionsItems, 0), STRING_TRIM)); |
| 191 | + string optionString = llList2String(optionsItems, 1); |
| 192 | + string optionSetting = llToLower(llStringTrim(optionString, STRING_TRIM)); |
| 193 | + integer optionSettingFlag = optionSetting=="on" || (integer)optionSetting; |
| 194 | + if(optionItem == "facialexp") { |
| 195 | + FacialEnable = optionSettingFlag; |
| 196 | + } |
| 197 | + } |
| 198 | + } |
| 199 | + } |
| 200 | + |
| 201 | + run_time_permissions(integer perm) { |
| 202 | + ThisAV = llGetPermissionsKey(); |
| 203 | + //start timer if we have face anims for any slot |
| 204 | + if(GotFaceAnim==1) { |
| 205 | + llSetTimerEvent(1.0); |
| 206 | + } |
| 207 | + else { |
| 208 | + llSetTimerEvent(0.0); |
| 209 | + } |
| 210 | + } |
| 211 | + |
| 212 | + timer() { |
| 213 | + integer n; |
| 214 | + integer SlotStop = llGetListLength(Slots)/8; |
| 215 | + key av; |
| 216 | + integer facecount; |
| 217 | + integer faceindex; |
| 218 | + if(FacialEnable) { |
| 219 | + for(n=0; n<SlotStop; ++n) { |
| 220 | + //doing each seat |
| 221 | + av = (key)llList2String(Slots, n*8+4); |
| 222 | + faceindex = 0; |
| 223 | + //locate our stride in FaceTimes list |
| 224 | + integer keyHasFacial = llListFindList(FaceTimes, [av]); |
| 225 | + //get number of face anims for this seat |
| 226 | + integer newFaceTimeFlag = llList2Integer(FaceTimes, keyHasFacial+1); |
| 227 | + |
| 228 | + if(newFaceTimeFlag == 0) { |
| 229 | + //need to know if someone seated in this seat, if not we won't do any facials |
| 230 | + if(av != "") { |
| 231 | + Faceanims = llParseString2List(llList2String(Slots, n*8+3), ["~"], []); |
| 232 | + facecount = llGetListLength(Faceanims); |
| 233 | + if(facecount > 0 && (llListFindList(SeatedAvs(), [ThisAV]) != -1)) {//modified cause face anims were being imposed after AV stands. |
| 234 | + ThisAV = llGetPermissionsKey(); |
| 235 | + llRequestPermissions(av, PERMISSION_TRIGGER_ANIMATION); |
| 236 | + } |
| 237 | + } |
| 238 | + integer x; |
| 239 | + for(x=0; x<facecount; ++x){ |
| 240 | + if (facecount>0) { |
| 241 | + if(faceindex < facecount) { |
| 242 | + if(AvLinkNum(av) != -1) { |
| 243 | + llStartAnimation(llList2String(Faceanims, faceindex)); |
| 244 | + } |
| 245 | + } |
| 246 | + faceindex++; |
| 247 | + } |
| 248 | + } |
| 249 | + } |
| 250 | + else if(av != ""){ |
| 251 | + //need to know if someone seated in this seat, if not we won't do any facials |
| 252 | + //do our stuff with defined facial times |
| 253 | + facecount = llList2Integer(FaceTimes, keyHasFacial+2); |
| 254 | + //if we have facial anims make sure we have permissions for this av |
| 255 | + if((facecount > 0) && (llListFindList(SeatedAvs(), [ThisAV]) != -1)) { //modified cause face anims were being imposed after AV stands. |
| 256 | + ThisAV = llGetPermissionsKey(); |
| 257 | + llRequestPermissions(av, PERMISSION_TRIGGER_ANIMATION); |
| 258 | + } |
| 259 | + integer x; |
| 260 | + for(x=1; x<=facecount; ++x) { |
| 261 | + //non looping we check if anim has run long enough |
| 262 | + if(faceindex < facecount) { |
| 263 | + integer faceStride = keyHasFacial+1+(x*2); |
| 264 | + string animName = llList2String(FaceTimes, faceStride); |
| 265 | + if(llList2Integer(FaceTimes, faceStride+1) > 0) { |
| 266 | + FaceTimes = llListReplaceList(FaceTimes, [llList2Integer(FaceTimes, faceStride+1)-1], |
| 267 | + faceStride+1, faceStride+1); |
| 268 | + } |
| 269 | + if(facecount>0) { |
| 270 | + if(AvLinkNum(av) != -1 && llList2Integer(FaceTimes, faceStride+1) > 0) { |
| 271 | + llStartAnimation(animName); |
| 272 | + } |
| 273 | + else if(AvLinkNum(av) != -1 && llList2Integer(FaceTimes, faceStride+1) == -1) { |
| 274 | + llStartAnimation(animName); |
| 275 | + } |
| 276 | + faceindex++; |
| 277 | + } |
| 278 | + } |
| 279 | + } |
| 280 | + |
| 281 | + } |
| 282 | + } |
| 283 | + if(llGetListLength(SeatedAvs())<1) { |
| 284 | + llSetTimerEvent(0.0); |
| 285 | + } |
| 286 | + } |
| 287 | + } |
| 288 | + |
| 289 | + changed(integer change) { |
| 290 | + if(change & CHANGED_LINK) { |
| 291 | + integer newPrimCount1 = llGetNumberOfPrims(); |
| 292 | + if(Newprimcount>newPrimCount1) { |
| 293 | + //we have lost a sitter so find out who and remove them from the list. |
| 294 | + integer n; |
| 295 | + integer LaStop = llGetListLength(Lastanim)/2; |
| 296 | + for(; n<LaStop; ++n) { |
| 297 | + if(AvLinkNum((key)llList2String(Lastanim, n*2)) == -1) { |
| 298 | + integer index = llListFindList(AnimsList, [(key)llList2String(Lastanim, n*2)]); |
| 299 | + if(index != -1) { |
| 300 | + AnimsList = llDeleteSubList(AnimsList, index, index + 2); |
| 301 | + } |
| 302 | + Lastanim = llDeleteSubList(Lastanim, n*2, n*2+1); |
| 303 | + } |
| 304 | + } |
| 305 | + } |
| 306 | + Newprimcount = newPrimCount1; |
| 307 | + } |
| 308 | + } |
| 309 | +} |
0 commit comments