Advertisement
Guest User

Active NPC contoller

a guest
Jul 29th, 2024
62
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 67.40 KB | None | 0 0
  1. integer channel = 68;
  2. integer PEG_CHAN=699;
  3. integer TIMER_INTERVAL=5; // how often to run the timer ////DEFAULT IS 5
  4. integer autoLoadOnReset=0;
  5. string LASTNAME="";
  6.  
  7.  
  8. // Nothing to edit here, see https://github.com/opensimworld/active-npcs for configuration
  9.  
  10. list availableNames = [];
  11. list lastNames = [];
  12. // These will be loaded from notecards
  13. list wNodes = [];
  14. list wLinks = [];
  15. list wNodeNames=[];
  16.  
  17. // list of nodes for the "Flyaround" command
  18. list flyTargets = [];
  19.  
  20. list menuItems = ["SaveNPC", "LoadNPC", "RemoveNPC", "RemoveAll", "LoadAll", "ReConfig","InitCmds", "DumpData", "TimerOnOff", "Close"];
  21.  
  22. string userInputState ="";
  23. integer gListener;
  24. integer zListener;
  25. integer howmany;
  26. list avis;
  27. integer curVisitors=1;
  28. integer deflectToNode = -1; // if set, the NPCs will only run notecards at the specified waypoint
  29.  
  30. list aviUids;
  31. list aviNames;
  32. list aviNodes;
  33. list aviPrevNodes;
  34. list aviStatus;
  35. list aviFollow;
  36. list aviCurrentAnim;
  37. list aviPath;
  38. list aviAlarm;
  39. list aviScriptIndex;
  40. list aviScriptText;
  41. list aviHttpId;
  42. list aviTarget; // user we are interacting with
  43. list scriptVars;
  44. list aviScriptState;
  45. list aviPrompts;
  46. list cache;
  47.  
  48.  
  49. integer aviIndex = -1;
  50. list seenArchive;
  51.  
  52. list positionsList;
  53. list greetedAvis;
  54. integer timerRuns;
  55. integer timerRunning;
  56. integer curPoint;
  57. integer prevPoint;
  58. list wayPoints;
  59. list wayNames;
  60. list wayLinks;
  61. list wayKeys;
  62. string name;
  63. key npc;
  64.  
  65. list candidateNode=[];
  66.  
  67.  
  68.  
  69. string vec2str(vector v)
  70. {
  71. return "<"+v.x+","+v.y+","+v.z+">";
  72. }
  73.  
  74. string GetLastName(string first)
  75. {
  76. integer idx = llListFindList(availableNames, [first]);
  77. if (idx >=0) return llList2String(lastNames, idx);
  78. else return LASTNAME;
  79. }
  80.  
  81. key getAgentByName(string firstName)
  82. {
  83. firstName = llToLower(firstName);
  84. list ag = osGetAvatarList();
  85. integer howmany = llGetListLength(ag);
  86. integer i;
  87. for (i =0; i < howmany; i+=3)
  88. {
  89. string name = llList2String(ag, i+2);
  90. integer sep = llSubStringIndex(name, " ");
  91. if (llToLower(llGetSubString(name, 0,sep-1)) == firstName)
  92. {
  93. return llList2Key(ag, i);
  94. }
  95. }
  96. return NULL_KEY;
  97. }
  98.  
  99. string GetScriptVar(string cmd3)
  100. {
  101. integer i;
  102. for (i=0; i < llGetListLength(scriptVars); i+=2)
  103. {
  104. if (llList2String(scriptVars,i) == cmd3 )
  105. {
  106. return llList2String(scriptVars, i+1);
  107. }
  108. }
  109. return ""; // default value;
  110. }
  111.  
  112.  
  113. integer ScriptJump(integer idx, string label, integer complain)
  114. {
  115. // Jump to a label in the notecard
  116. integer foundLine = FindScriptLineAfter(llList2String(aviScriptText,idx), "@"+label,-1);
  117. if (foundLine == -1)
  118. {
  119. if (complain) llOwnerSay("Error: @"+label+" label not found");
  120. return 0;
  121. }
  122. else
  123. {
  124. aviScriptIndex = []+llListReplaceList(aviScriptIndex, [foundLine+1], idx, idx);
  125. return 1;
  126. }
  127. }
  128.  
  129. list permList;
  130. string permCache;
  131.  
  132. LoadPerms()
  133. {
  134. permList=[];
  135. permCache = "";
  136. if (llGetInventoryType("__permissions")==INVENTORY_NOTECARD)
  137. {
  138. llOwnerSay("Loading Permissions...");
  139. list lines = llParseString2List(osGetNotecard("__permissions"), ["\n"], []);
  140. integer l;
  141. for (l=0;l<llGetListLength(lines);l++)
  142. {
  143. list tk = llParseString2List(llList2String(lines,l), [" "], []);
  144. if (llList2String(tk,2) == "=")
  145. {
  146. string kw = llList2String(tk,3);
  147. string rule=llToLower(llList2String(tk,0)+" "+llList2String(tk,1));
  148. string n= llToLower(llStringTrim(llList2String(tk,4)+ " " + llList2String(tk,5), STRING_TRIM));
  149. if (n == "" ) n= "*";
  150. string val=kw+"|"+n+"|";
  151. permList+=rule;
  152. permList+=kw;
  153. permList+=n;
  154. if (llSubStringIndex(permCache,rule)<0) permCache+= rule;
  155. }
  156. }
  157. llOwnerSay(llList2CSV(permList));
  158. llOwnerSay(llList2CSV(permCache));
  159. }
  160. }
  161.  
  162.  
  163. integer IsAllowed(string npc, string cmd, key uid)
  164. {
  165. if (uid == llGetOwner() || llGetListLength(permList)==0) return 1;
  166.  
  167. string ss = "* *";
  168. string ns = npc+" *";
  169. string sc = "* "+cmd;
  170. string nc = npc+" "+cmd;
  171.  
  172. if (llSubStringIndex(permCache, ss)<0 && llSubStringIndex(permCache, ns)<0 && llSubStringIndex(permCache, sc)<0 && llSubStringIndex(permCache, nc)<0 ) return 1;
  173.  
  174. integer allow=1;
  175. string name = llToLower(llKey2Name(uid));
  176. integer k;
  177. for (k=0; k< llGetListLength(permList); k+=3)
  178. {
  179. string rule = llList2String(permList,k);
  180. if (rule==ss || rule==ns || rule==sc || rule==nc)
  181. {
  182. //llOwnerSay("R="+rule);
  183. string r = llList2String(permList, k+1);
  184. if (r =="ALLOW" || r == "DENY")
  185. {
  186. string who=llList2String(permList, k+2);
  187. if (who == "*" || who==name)
  188. {
  189. if (r == "ALLOW") allow=1;
  190. else allow=0;
  191. }
  192. }
  193. else if (r=="ALLOWID")
  194. {
  195. if ( uid == llList2Key(permList, k+2)) allow=1;
  196. }
  197. else if (r=="DENYID")
  198. {
  199. if ( uid == llList2Key(permList, k+2)) allow=0;
  200. }
  201. else if (r =="ALLOWSAMEGROUP")
  202. {
  203. if ( llSameGroup(uid)) {
  204. allow=1;
  205. }
  206. }
  207. }
  208. }
  209. return allow;
  210. }
  211.  
  212.  
  213.  
  214. ReloadConfig()
  215. {
  216. availableNames = [];
  217. lastNames = [];
  218. list tk = llParseString2List(osGetNotecard("__npc_names"), ["\n"] , []);
  219. integer i=0;
  220. for (i=0; i < llGetListLength(tk); i++)
  221. {
  222. list t2 = llParseString2List(llList2String(tk,i), [" "] , []);
  223. string f = llList2String(t2, 0);
  224. string l = llList2String(t2, 1);
  225. if (l =="") l = LASTNAME;
  226. if (f != "")
  227. {
  228. availableNames += f;
  229. lastNames += l;
  230. }
  231. }
  232. llOwnerSay("npc_names: "+llList2CSV(availableNames));
  233.  
  234. flyTargets = llParseString2List(osGetNotecard("__fly_targets"), [" ", "\n", ""] , []);
  235.  
  236. string ncName = "__config";
  237. autoLoadOnReset=0;
  238.  
  239. if (llGetInventoryType(ncName) == INVENTORY_NOTECARD)
  240. {
  241. list tok = llParseString2List(osGetNotecard("__config"), ["=", "\n"] , []);
  242. integer j;
  243. for (j=0; j < llGetListLength(tok); j+=2)
  244. {
  245. string opt = llList2String(tok,j);
  246. if (opt== "AutoLoadOnReset") autoLoadOnReset = (integer)llList2String(tok, j+1);
  247. else if (opt== "LastName") LASTNAME = llList2String(tok, j+1);
  248. }
  249. }
  250. if (LASTNAME == "") LASTNAME = "(NPC)";
  251.  
  252. LoadPerms();
  253.  
  254. }
  255.  
  256.  
  257. integer countVisitors()
  258. {
  259. list avis = llGetAgentList(AGENT_LIST_REGION, []);
  260. integer howmany = llGetListLength(avis);
  261. integer i;
  262. integer nNew =0;
  263. for ( i = 0; i < howmany; i++ ) {
  264. if ( ! osIsNpc(llList2Key(avis, i)) )
  265. {
  266. nNew++; // only non-NPC's
  267. key uu = llList2Key(avis, i);
  268. string nm = llKey2Name(uu);
  269. if (nm != "")
  270. {
  271. integer fnd = llListFindList(seenArchive, [nm]);
  272. if (fnd >=0)
  273. seenArchive = [] + llListReplaceList(seenArchive, [nm, llGetUnixTime()], fnd, fnd+1);
  274. else
  275. seenArchive = [] + seenArchive + [nm, llGetUnixTime()];
  276. }
  277. }
  278. }
  279. return nNew;
  280. }
  281.  
  282. doLoadNPC(string first, string last)
  283. {
  284. integer idx =(GetNPCIndex(first));
  285. if (idx >=0)
  286. {
  287. llOwnerSay(first+ " is already in region, not loading");
  288. osNpcStand(llList2Key(aviUids, idx));
  289. return;
  290. }
  291.  
  292. key unpc = osNpcCreate(first, last, llGetPos()+<3,0,3>, "APP_"+llToLower(first), OS_NPC_SENSE_AS_AGENT );
  293. if (unpc != NULL_KEY)
  294. doAddNpc(first, unpc);
  295. }
  296.  
  297.  
  298. doAddNpc(string name, string unpc)
  299. {
  300.  
  301. llOwnerSay( "Adding '"+name+"'");
  302. aviUids += unpc;
  303. aviNames += llToLower(name);
  304. aviNodes += 1;
  305. aviPrevNodes += 0;
  306. aviStatus += "";
  307. aviFollow += "";
  308. aviCurrentAnim += "";
  309. aviHttpId += "";
  310. aviAlarm += -1;
  311. aviScriptIndex += -1;
  312. aviScriptText += "";
  313. aviTarget += NULL_KEY;
  314. aviPath += "";
  315. aviScriptState += "";
  316. aviPrompts += "";
  317. osNpcMoveToTarget(unpc, osNpcGetPos(unpc) + <1,0,0>, OS_NPC_NO_FLY );
  318. }
  319.  
  320. doRemoveNpc(string who)
  321. {
  322. integer idx = GetNPCIndex(who);
  323. if (idx <0) return;
  324.  
  325. key u = llList2Key(aviUids, idx);
  326. aviNames = [] + llDeleteSubList(aviNames, idx, idx);
  327. aviUids = [] + llDeleteSubList(aviUids, idx, idx);
  328. aviNodes = [] + llDeleteSubList(aviNodes, idx, idx);
  329. aviPrevNodes = [] + llDeleteSubList(aviNodes, idx, idx);
  330. aviFollow = [] + llDeleteSubList(aviFollow, idx, idx); [];
  331. aviStatus = [] + llDeleteSubList(aviStatus, idx, idx);
  332. aviCurrentAnim = [] + llDeleteSubList(aviCurrentAnim, idx, idx);
  333. aviPath = [] + llDeleteSubList(aviPath, idx, idx);
  334. aviHttpId = [] + llDeleteSubList(aviHttpId, idx, idx);
  335. aviAlarm = [] + llDeleteSubList(aviAlarm, idx, idx);
  336. aviScriptIndex = [] + llDeleteSubList(aviScriptIndex, idx, idx);
  337. aviScriptText = [] + llDeleteSubList(aviScriptText, idx, idx);
  338. aviTarget = [] + llDeleteSubList(aviTarget, idx, idx);
  339. aviScriptState = [] + llDeleteSubList(aviScriptState, idx, idx);
  340. aviPrompts = [] + llDeleteSubList(aviPrompts, idx, idx);
  341.  
  342. llOwnerSay("Removing "+who + "");
  343. osNpcStand(u);
  344. osNpcRemove(u);
  345. }
  346.  
  347. doLoadAll()
  348. {
  349. integer i;
  350. for (i=0; i < llGetListLength(availableNames);i++)
  351. {
  352. doLoadNPC(llList2String(availableNames, i), llList2String(lastNames, i));
  353. }
  354.  
  355. }
  356.  
  357.  
  358. doInitCmds()
  359. {
  360. string notecard= "__initcommands";
  361. integer i;
  362. for(i=0; i<=osGetNumberOfNotecardLines(notecard); i++) {
  363. string line = llStringTrim(osGetNotecardLine(notecard, i), STRING_TRIM);
  364. if (llStringLength(line)>0 && line != "")
  365. {
  366. list l = llParseString2List(line, [" "], []);
  367. line = "! "+(string)NULL_KEY+" "+llList2String(l,0)+" "+ line;
  368. llOwnerSay("InitCmd="+line);
  369. ProcessNPCCommand(line);
  370. }
  371. }
  372.  
  373. }
  374.  
  375. setVar(string cmd2, string cmd3)
  376. {
  377. integer i;
  378. for (i=0; i < llGetListLength(scriptVars); i+=2)
  379. {
  380. if (llList2String(scriptVars,i) == cmd2)
  381. {
  382. scriptVars = [] + llListReplaceList(scriptVars, [cmd3], i+1, i+1);
  383. return;
  384. }
  385. }
  386. scriptVars += cmd2;
  387. scriptVars += cmd3;
  388. }
  389.  
  390.  
  391. integer RescanAvis()
  392. {
  393. avis = osGetAvatarList();
  394. howmany = llGetListLength(avis);
  395. integer i;
  396. for (i =0; i < howmany; i+=3)
  397. {
  398. if (osIsNpc(llList2Key(avis, i)))
  399. {
  400. integer sep = llSubStringIndex(llList2Key(avis, i+2), " ");
  401. string nm = llGetSubString(llList2Key(avis, i+2), 0, sep-1 );
  402. doAddNpc(nm, llList2Key(avis, i));
  403. }
  404. }
  405. llOwnerSay(llList2CSV(aviNames));
  406. llOwnerSay(llList2CSV(aviStatus));
  407. return llGetListLength(aviUids);
  408. }
  409.  
  410.  
  411. LoadMapData()
  412. {
  413. integer tl = osGetNumberOfNotecardLines("__waypoints");
  414. integer i;
  415. wNodes = [];
  416. for (i=0; i < tl; i++)
  417. {
  418. string line = osGetNotecardLine("__waypoints",i);
  419. list tok = llParseStringKeepNulls(line, [","], []);
  420. float x = llList2Float(tok,0);
  421. if (x>0)
  422. {
  423. vector v = <llList2Float(tok,0), llList2Float(tok,1),llList2Float(tok,2)>;
  424. wNodes += v;
  425. wNodeNames += llList2String(tok,3);
  426. }
  427. }
  428. llOwnerSay("loaded "+(string)(llGetListLength(wNodes))+" waypoints");
  429.  
  430.  
  431. integer tnodes = llGetListLength(wNodes);
  432. wLinks = [];
  433. tl = osGetNumberOfNotecardLines("__links");
  434. for (i=0; i < tl; i++)
  435. {
  436. string line = osGetNotecardLine("__links",i);
  437. list tok = llParseString2List(line, [","],"");
  438. integer a= llList2Integer(tok,0);
  439. integer b = llList2Integer(tok,1);
  440. if (a !=b)
  441. wLinks += [a,b];
  442. }
  443. llOwnerSay("loaded "+(string)(llGetListLength(wLinks)/2)+" links");
  444. cache = [];
  445. }
  446.  
  447.  
  448. integer GetNPCIndex(string name) /// name is in lowercase
  449. {
  450. return llListFindList(aviNames, [llToLower(name)]);
  451. }
  452.  
  453.  
  454. integer GetWalkTime(float distance)
  455. {
  456. return llCeil(distance / 1.7);
  457. }
  458.  
  459. integer GetNearestNode(vector pos)
  460. {
  461. integer i;
  462. float min = 9999991.;
  463. integer l =-1;
  464. for (i=0;i < llGetListLength(wNodes); i++)
  465. {
  466. float dist = llVecDist(pos, llList2Vector(wNodes,i));
  467. if (dist < min)
  468. {
  469. min = dist;
  470. l=i;
  471. }
  472. }
  473. return l;
  474. }
  475.  
  476. list foundPaths;
  477. // Get path through LSL -- Slow
  478. integer GenPaths(integer a, integer tgt, string path, integer depth)
  479. {
  480. if (depth > 17)
  481. {
  482. //llOwnerSay("Bailing at " + path);
  483. return 0;
  484. }
  485. integer i;
  486. for (i=0; i < llGetListLength(wLinks); i+=2)
  487. {
  488. integer ca = llList2Integer(wLinks, i);
  489. integer cb = llList2Integer(wLinks, i+1);
  490. integer fn = -1;
  491. if (cb == a || ca == a)
  492. {
  493. if (cb == a)
  494. fn = ca;
  495. else if (ca == a)
  496. fn = cb;
  497. if (llSubStringIndex(path, ":"+fn+":")<0)
  498. {
  499. if (fn == tgt)
  500. {
  501. path += ""+fn+":";
  502. foundPaths += (path);
  503. return 1;
  504. }
  505. else
  506. {
  507.  
  508. GenPaths(fn, tgt, path+fn+":", depth+1);
  509. }
  510. }
  511. }
  512.  
  513. if (llGetListLength(foundPaths)>30)
  514. return 2;
  515. }
  516. return 0;
  517. }
  518.  
  519.  
  520.  
  521.  
  522.  
  523. string GetGotoPath(integer nodeA, integer nodeB)
  524. {
  525. integer i;
  526. integer ww;
  527.  
  528.  
  529. string tmpPath = ":"+(string)nodeA+":";
  530.  
  531. foundPaths = [];
  532. GenPaths(nodeA, nodeB, tmpPath, 0);
  533. //llOwnerSay(llList2CSV(foundPaths));
  534. if (llGetListLength(foundPaths) ==0)
  535. return "";
  536. integer min = 99999;
  537. string least = "";
  538. for (i=0; i < llGetListLength(foundPaths); i++)
  539. {
  540. ww = llStringLength(llList2String(foundPaths, i));
  541. if (ww < min)
  542. {
  543. min = ww;
  544. least = llList2String(foundPaths, i);
  545. }
  546. }
  547. //llOwnerSay(least);
  548. return least;
  549. }
  550.  
  551.  
  552.  
  553. integer GetNPCIndexByUid(key name)
  554. {
  555. return llListFindList(aviUids, [name]);
  556. }
  557.  
  558.  
  559. string GetScriptLine(string scriptData, integer line)
  560. {
  561. list scriptLines = llParseStringKeepNulls(scriptData, ["\n",";"], []);
  562. return llList2String(scriptLines, line-1);
  563. }
  564.  
  565. integer FindScriptLineAfter(string scriptData, string lineToFind, integer afterLine)
  566. {
  567. integer endIdx;
  568. list scriptLines = llParseStringKeepNulls(scriptData, ["\n",";"], []);
  569. string toFind = llToLower(lineToFind);
  570. integer foundLine = -1;
  571. string line;
  572. for (endIdx = afterLine+1;endIdx < llGetListLength(scriptLines); endIdx++)
  573. {
  574. line = llList2String(scriptLines, endIdx);
  575. if (llStringTrim(line, STRING_TRIM) == toFind)
  576. {
  577. foundLine =endIdx;
  578. jump _foundIdxOut;
  579. }
  580. }
  581. @_foundIdxOut;
  582. return foundLine;
  583. }
  584.  
  585.  
  586. integer FindMatchingEndif(string scriptData, integer afterLine)
  587. {
  588. integer endIdx;
  589. list scriptLines = llParseStringKeepNulls(scriptData, ["\n",";"], []);
  590. string toFind = "end-if";
  591. integer foundLine = -1;
  592. string line;
  593. integer ifLevel=1;
  594. for (endIdx = afterLine+1;endIdx < llGetListLength(scriptLines); endIdx++)
  595. {
  596. line = llStringTrim(llList2String(scriptLines, endIdx), STRING_TRIM);
  597. if (llGetSubString(line, 0, 1) == "if")
  598. {
  599. ifLevel++;
  600. }
  601. else if (line == "end-if")
  602. {
  603. ifLevel--;
  604. if (ifLevel==0)
  605. {
  606. foundLine =endIdx;
  607. jump _foundEIIdxOut;
  608. }
  609. }
  610. }
  611. @_foundEIIdxOut;
  612. return foundLine;
  613. }
  614.  
  615. integer GetNodeIndexByName(string nodeName)
  616. {
  617. integer i;
  618. nodeName = llToLower(nodeName);
  619. for (i=0; i < llGetListLength(wNodeNames); i++)
  620. {
  621. if (llToLower(llList2String(wNodeNames, i)) == nodeName)
  622. {
  623. return i;
  624. }
  625. }
  626. return -1;
  627. }
  628.  
  629. SetScriptAlarm(integer aviId, integer time)
  630. {
  631. aviAlarm = [] + llListReplaceList(aviAlarm, [llGetUnixTime() + time], aviId, aviId);
  632. }
  633.  
  634.  
  635. doStopNpc(integer idx, key uNPC)
  636. {
  637. aviStatus = [] + llListReplaceList(aviStatus, [""], idx, idx);
  638. SetScriptAlarm(idx, 0);
  639. list anToStop=llGetAnimationList(uNPC);
  640. integer stop=llGetListLength(anToStop);
  641. while (--stop>=0) { osNpcStopAnimation(uNPC,llList2Key(anToStop,stop)); }
  642. osNpcStopMoveToTarget(uNPC);
  643. osNpcStand(uNPC);
  644. }
  645.  
  646. // Handler for all commands coming from chat
  647. integer ProcessNPCCommand(string inputString)
  648. {
  649.  
  650. list tokens = llParseString2List(inputString, [" "], []);
  651. // first token should be just "!"
  652.  
  653. //llOwnerSay("<<" + inputString);
  654. key sendUid = llList2Key(tokens,1);
  655. string npcName = llToLower(llList2String(tokens,2));
  656. string name2 = llToLower(llList2String(tokens,3));
  657. //if (npcName != name2) npcName = name2;
  658.  
  659. integer idx = GetNPCIndex(npcName);
  660. if (idx <0)
  661. {
  662. return 1;
  663. }
  664.  
  665. key uNPC= llList2Key(aviUids, idx);
  666. if (uNPC == NULL_KEY)
  667. {
  668. return 1;
  669. }
  670.  
  671.  
  672.  
  673. if (llSubStringIndex(inputString, "$")>=0) //substiute variables
  674. {
  675. integer i;
  676. for (i=4; i < llGetListLength(tokens); i++)
  677. {
  678. string st = llList2String(tokens,i);
  679. if (llSubStringIndex(st, "$")==0)
  680. {
  681. tokens = [] + llListReplaceList(tokens, [ GetScriptVar(llGetSubString(st,1,-1) ) ], i , i);
  682. }
  683. }
  684. }
  685.  
  686. string cmd1= llList2String(tokens,4);
  687. string cmd2= llList2String(tokens,5);
  688. list userData;
  689.  
  690. if (sendUid!= NULL_KEY && (llGetAgentSize(sendUid) != ZERO_VECTOR))
  691. {
  692. if (!IsAllowed(npcName, cmd1, sendUid))
  693. {
  694. llOwnerSay("Denied '"+cmd1+"' to "+(string)sendUid+" "+llKey2Name(sendUid));
  695. return 1;
  696. }
  697. }
  698.  
  699.  
  700. if (llList2String(aviStatus, idx) == "prompt")
  701. {
  702. aviStatus = []+llListReplaceList(aviStatus, [""], idx, idx); // Turn off prompt in sync with the listener
  703. if (npcName != name2 ) // it (probably) a response to the prompt, rather than a command given to the npc
  704. {
  705. integer i;
  706. for (i=3; i < llGetListLength(tokens); i++)
  707. {
  708.  
  709. if ( llSubStringIndex(llList2String(aviPrompts, idx), "["+llToLower(llList2String(tokens, i))+"]" ) > 0) // label existed in prompt
  710. {
  711. aviTarget = []+llListReplaceList(aviTarget, [sendUid], idx, idx);
  712. ScriptJump(idx, llToLower(llList2String(tokens, i)) , 1);
  713. return 1;
  714. }
  715. }
  716. return 1;
  717. }
  718. }
  719.  
  720.  
  721. if (cmd1 == "stop")
  722. {
  723. doStopNpc(idx, uNPC);
  724. }
  725. else if (cmd1 == "come")
  726. {
  727. doStopNpc(idx, uNPC);
  728. userData=llGetObjectDetails((key)sendUid, [OBJECT_NAME,OBJECT_POS, OBJECT_ROT]);
  729. osNpcStopMoveToTarget(uNPC);
  730. osTeleportAgent(uNPC, llList2Vector(userData, 1) + <1, 0, 0>, <1,1,1>);
  731. if (sendUid != NULL_KEY) // NOTE: a real avatar sent this command - stop processing our script
  732. aviScriptIndex = []+llListReplaceList(aviScriptIndex, -1, idx, idx);
  733. }
  734. else if (cmd1 == "stand")
  735. {
  736. aviStatus = []+llListReplaceList(aviStatus, [""], idx, idx);
  737. osNpcStand(uNPC);
  738. osNpcStopMoveToTarget(uNPC);
  739. }
  740. else if (cmd1 == "moveto" || cmd1 == "movetov" || cmd1 == "runtovr"|| cmd1 == "movetovr" || cmd1 == "flytov" || cmd1 == "runtov" || cmd1=="walk" )
  741. {
  742. // Walk to the specified waypoint or vector
  743. vector v;
  744. string anim =""; // Specify an animation to play while walking
  745. if (cmd1 == "runtovr"||cmd1 == "movetovr")
  746. {
  747. // run to somewhere within the volume enclosed by v1 and v2
  748. vector v1 = (vector) cmd2;
  749. vector v2 = (vector) llList2String(tokens, 6);
  750. v.x= v1.x + llFrand(v2.x-v1.x);
  751. v.y= v1.y + llFrand(v2.y-v1.y);
  752. v.z= v1.z + llFrand(v2.z-v1.z);
  753. anim = llList2String(tokens, 7);
  754. }
  755. else if (cmd1 == "movetov" || cmd1 == "flytov" ||cmd1 == "runtov" || cmd1 =="walk")
  756. {
  757. v = (vector)cmd2;
  758. if (v == ZERO_VECTOR)
  759. {
  760. llOwnerSay(npcName + ": "+cmd2+" is not a good position. I am not going there!");
  761. return 1;
  762. }
  763. anim = llList2String(tokens, 6);
  764. }
  765. else
  766. v = llList2Vector(wNodes, (integer)cmd2);
  767.  
  768. float dist = llVecDist(osNpcGetPos(uNPC), v);
  769.  
  770. if (cmd1 == "runtovr"|| cmd1 == "runtov")
  771. {
  772. osSetSpeed(uNPC, 1.0);
  773. osNpcMoveToTarget(uNPC, v + <0,0,1>, OS_NPC_NO_FLY | OS_NPC_RUNNING);
  774. SetScriptAlarm(idx, (integer)(GetWalkTime(dist)/2.));
  775. }
  776. else
  777. {
  778. if (anim == "")
  779. osNpcStand(uNPC);
  780. osNpcStopMoveToTarget(uNPC);
  781. osSetSpeed(uNPC, 0.5);
  782. if (cmd1 == "flytov")
  783. osNpcMoveToTarget(uNPC, v + <0,0,1>, OS_NPC_FLY );
  784. else
  785. osNpcMoveToTarget(uNPC, v + <0,0,1>, OS_NPC_NO_FLY);
  786. if (anim)
  787. {
  788. llSleep(0.5);
  789. osNpcPlayAnimation(uNPC, anim);
  790. }
  791.  
  792. SetScriptAlarm(idx, GetWalkTime(dist));
  793. }
  794. }
  795. else if (cmd1 == "setvar")
  796. {
  797. string cmd3 = llList2String(tokens,6);
  798. setVar(cmd2, cmd3);
  799. return 0;
  800. }
  801. else if (cmd1 == "if" || cmd1 == "if-not" || cmd1=="if-prob")
  802. {
  803. integer res = 0;
  804. if (cmd1 == "if-prob")
  805. {
  806. if (llFrand(1.0)<(float)cmd2)
  807. res = 1;
  808. }
  809. else if (cmd2 == "name-is")
  810. {
  811. integer k;
  812. res=0;
  813. for (k=6; k < llGetListLength(tokens); k++)
  814. {
  815. if (llToLower(npcName) == llToLower(llList2String(tokens,k)))
  816. {
  817. setVar("_found", npcName);
  818. res=1;
  819. }
  820. }
  821. }
  822. else if (cmd2 == "var-is")
  823. {
  824. integer k;
  825. res=0;
  826. for (k=6; k < llGetListLength(tokens); k+=2)
  827. {
  828. string nm = llList2String(tokens,k);
  829. if (nm == "") jump varIsBreak;
  830. string val = llList2String(tokens,k+1);
  831. if (GetScriptVar(nm) == val)
  832. res =1;
  833. else
  834. {
  835. res=0;
  836. jump varIsBreak;
  837. }
  838. }
  839. @varIsBreak;
  840. }
  841. else if (cmd2 == "state-is")
  842. {
  843. // If state-is <avi-name> <state-value>
  844. integer nwho = GetNPCIndex(llList2String(tokens,6));
  845. if (nwho >=0)
  846. {
  847. string what = llList2String(aviScriptState,nwho);
  848. integer k;
  849. for (k=7; k < llGetListLength(tokens); k++)
  850. {
  851. if (what == llList2String(tokens,k))
  852. res=1;
  853. }
  854. }
  855. }
  856.  
  857. if (cmd1 == "if-not")
  858. res = !res;
  859.  
  860. integer scrline = llList2Integer(aviScriptIndex, idx);
  861. if (scrline <0)
  862. {
  863. return 1; // wtf
  864. }
  865.  
  866. if (!res)
  867. {
  868. integer foundLine = FindMatchingEndif(llList2String(aviScriptText,idx), scrline-1); /// this used to skip a line
  869. if (foundLine == -1)
  870. {
  871. llOwnerSay("Error: end-if not found afterr "+cmd1 + " "+cmd2 + "...");
  872. }
  873. else
  874. {
  875. aviScriptIndex = []+llListReplaceList(aviScriptIndex, [foundLine+1], idx, idx);// Go past the end-if -- runs notecards faster
  876. }
  877. }
  878. return 0;
  879. }
  880. else if (cmd1 == "end-if")
  881. {
  882. // Do nothing
  883. return 0;
  884. }
  885. else if (cmd1 == "prompt")
  886. {
  887. string prompt = llDumpList2String(llList2List(tokens, 5, -1), " ");
  888. aviStatus = []+llListReplaceList(aviStatus, ["prompt"], idx, idx);
  889. osNpcSay(uNPC, prompt);
  890. aviPrompts = []+llListReplaceList(aviPrompts, [llToLower(inputString)], idx, idx);
  891. aviTarget = []+llListReplaceList(aviTarget, [NULL_KEY], idx, idx);
  892. osMessageAttachments(uNPC, "prompt", [ATTACH_RIGHT_PEC], 0);
  893. }
  894. else if (cmd1 == "jump")
  895. {
  896. // Jump to a label in the notecard
  897. ScriptJump(idx, llToLower(cmd2), 1);
  898. return 0; // process next cmd immediately
  899. }
  900. else if ((cmd1 == "go" && cmd2 == "to") || cmd1 == "goto")
  901. {
  902. // Pathfinding command
  903. integer nearest = GetNearestNode(osNpcGetPos(uNPC));
  904. integer foundId =-1;
  905. if (cmd1 == "goto")
  906. {
  907. foundId = (integer) cmd2;
  908. }
  909. else
  910. {
  911. string where = llToLower(llStringTrim(llList2String(tokens,6) +" "+ llList2String(tokens,7) +" "+ llList2String(tokens,8), STRING_TRIM));
  912. integer i;
  913. if (where != "")
  914. foundId = GetNodeIndexByName(where);
  915.  
  916. if (foundId <0)
  917. {
  918. list tmp;
  919. for (i=0; i < llGetListLength(wNodeNames); i++)
  920. if (llList2String(wNodeNames,i) != "")
  921. tmp += llList2String(wNodeNames, i);
  922. osNpcSay(uNPC, "Sorry i dont know how to get to the "+where+ ". Here's some of the places i know: " +llList2CSV(tmp));
  923. return 1;
  924. }
  925. }
  926.  
  927. osNpcSay(uNPC, "Let me think... ");
  928. string cachekey = "f,"+(string)nearest+","+(string)foundId;
  929. string gotoPath ="";
  930. integer fidx = llListFindList(cache, [cachekey]);
  931. if (fidx>=0)
  932. {
  933. gotoPath = llList2String(cache, fidx+1);
  934. }
  935. else
  936. {
  937. gotoPath = GetGotoPath(nearest, foundId);
  938. if (gotoPath != "")
  939. {
  940. cache += cachekey;
  941. cache += gotoPath;
  942. }
  943. }
  944. if (gotoPath == "")
  945. {
  946. osNpcSay(uNPC, "I 'm dumb. i don't know how to get there ... ");
  947. return 1;
  948. }
  949. osNpcSay(uNPC, "If you want to go there, follow me.");
  950. SetScriptAlarm(idx, 0);
  951. aviPath = []+ llListReplaceList(aviPath, [gotoPath], idx, idx);
  952. aviStatus = []+llListReplaceList(aviStatus, ["pathf"], idx, idx);
  953. }
  954. else if (cmd1 == "setpath")
  955. {
  956. //Path must be in format 2:4:63:22:1 where the numbers are the waypoints numbers
  957. aviPath = []+ llListReplaceList(aviPath, [cmd2], idx, idx);
  958. SetScriptAlarm(idx, 0);
  959. aviStatus = []+llListReplaceList(aviStatus, ["pathf"], idx, idx);
  960. }
  961. else if (cmd1 == "waitvar")
  962. {
  963. // Wait until the value of variable named cmd2 reaches the value cmd3
  964. string cmd3 = llList2String(tokens,6);
  965. string vval = GetScriptVar(cmd2);
  966.  
  967. if (vval == cmd3)
  968. {
  969. return 1; /// OK continue with the next line
  970. }
  971. else if (cmd3 == "NONEMPTY" && vval != "")
  972. {
  973. return 1;
  974. }
  975.  
  976. integer scriptIndex = llList2Integer(aviScriptIndex, idx);
  977. if (scriptIndex>0)
  978. {
  979. aviScriptIndex = []+llListReplaceList(aviScriptIndex, [scriptIndex-1], idx, idx);
  980. }
  981. }
  982. else if (cmd1 == "increase" || cmd1 == "decrease" || cmd1 == "zero")
  983. {
  984. integer v = (integer)GetScriptVar(cmd2);
  985. if (cmd1=="increase") v++;
  986. else if (cmd1 == "decrease") v--;
  987. else v=0;
  988. setVar(cmd2, (string)v);
  989. return 1;
  990. }
  991. else if (cmd1 == "wait")
  992. {
  993. integer tm = (integer)cmd2;
  994. integer tm2 = (integer)llList2String(tokens,6);
  995. if (tm2>0)
  996. tm = (integer)(tm + llFrand(tm2));
  997. SetScriptAlarm(idx, tm);
  998. }
  999. else if (cmd1 == "say" || cmd1 == "shout")
  1000. {
  1001. // Say something on chat
  1002. string txt = "";
  1003. integer i;
  1004. for (i=5; i < llGetListLength(tokens); i++)
  1005. txt += llList2String(tokens,i) + " ";
  1006. if (cmd1 == "shout")
  1007. osNpcShout(uNPC, 0, txt);
  1008. else
  1009. osNpcSay(uNPC, txt);
  1010. return 0;
  1011. }
  1012. else if (cmd1 == "saych")
  1013. {
  1014. // Say something on channel
  1015. string txt = "";
  1016. integer i;
  1017. for (i=6; i < llGetListLength(tokens); i++)
  1018. txt += llList2String(tokens,i) + " ";
  1019. osNpcSay(uNPC, llList2Integer(tokens,5), txt);
  1020. }
  1021. else if (cmd1 == "loadnpc")
  1022. {
  1023. doLoadNPC(cmd2, llList2String(tokens, 6));
  1024. }
  1025. else if (cmd1 == "removenpc")
  1026. {
  1027. doRemoveNpc(cmd2);
  1028. }
  1029. else if (cmd1 == "exec")
  1030. {
  1031. list tok2 = ["!", (string)NULL_KEY, cmd2] + llList2List(tokens, 5, -1);
  1032. //llOwnerSay(llList2CSV(tok2));
  1033. ProcessNPCCommand(llDumpList2String(tok2, " "));
  1034. }
  1035.  
  1036. else if (cmd1 == "msgatt")
  1037. {
  1038.  
  1039. list points = [];
  1040. integer i;
  1041. for (i=6; i < llGetListLength(tokens); i++)
  1042. {
  1043. if (llList2Integer(tokens, i)>0)
  1044. points += llList2Integer(tokens,i);
  1045. }
  1046. osMessageAttachments(uNPC, cmd2, points, 0);
  1047. }
  1048. else if (cmd1 == "teleport")
  1049. {
  1050. vector w = (vector) cmd2;
  1051. if (w == ZERO_VECTOR)
  1052. {
  1053. integer where = GetNodeIndexByName(cmd2);
  1054. if (where >=0)
  1055. {
  1056. w = llList2Vector(wNodes, where);
  1057. osTeleportAgent(uNPC, w, <0,0,0>);
  1058. }
  1059. }
  1060. else osTeleportAgent(uNPC, w, <0,0,0>);
  1061. }
  1062. else if (cmd1 == "use")
  1063. {
  1064. // Sit-on-a-poseball command
  1065. string cmd = llStringTrim(cmd2+" "+llList2String(tokens, 6)+" "+llList2String(tokens,7), STRING_TRIM);
  1066. osMessageAttachments(uNPC, "do "+cmd, [ATTACH_RIGHT_PEC], 0);
  1067. }
  1068. else if (cmd1 == "lookat")
  1069. {
  1070. vector v;
  1071. if (cmd2=="me")
  1072. {
  1073. userData=llGetObjectDetails((key)sendUid, [OBJECT_NAME,OBJECT_POS, OBJECT_ROT]);
  1074. v = llList2Vector(userData,1);
  1075. }
  1076. else
  1077. {
  1078. v = (vector)cmd2;
  1079. if (v == ZERO_VECTOR)
  1080. {
  1081. integer midx = GetNodeIndexByName(llToLower(cmd2));
  1082. if (midx >=0)
  1083. {
  1084. v = llList2Vector(wNodes, midx);
  1085. }
  1086. }
  1087. }
  1088. osNpcSetRot(uNPC, llRotBetween(<1,0,0>, v-osNpcGetPos(uNPC)));//llEuler2Rot(<0,0,ang>));
  1089. }
  1090. else if (cmd1 == "anim")
  1091. {
  1092. osNpcStopAnimation(uNPC, llList2String(aviCurrentAnim, idx));
  1093. aviCurrentAnim = llListReplaceList(aviCurrentAnim, [cmd2], idx, idx);
  1094. osNpcPlayAnimation(uNPC, cmd2);
  1095. }
  1096. else if (cmd1 == "give")
  1097. {
  1098. if (llGetInventoryType(cmd2) == INVENTORY_OBJECT)
  1099. llGiveInventory(sendUid, cmd2);
  1100. }
  1101. else if (cmd1 == "light")
  1102. osMessageAttachments(uNPC, "light", [ATTACH_RIGHT_PEC], 0);
  1103. else if (cmd1 == "sound")
  1104. osMessageAttachments(uNPC, "sound " + cmd2+" "+llList2String(tokens, 6) , [ATTACH_RIGHT_PEC], 0);
  1105. else if (cmd1 == "batch")
  1106. {
  1107. // Run multiple commands from the chat, separated by ";" --- replaces any running script
  1108. string str = llDumpList2String(llList2List(tokens, 5, llGetListLength(tokens))," ");
  1109. aviScriptText = []+llListReplaceList(aviScriptText, str, idx, idx);
  1110. aviScriptIndex = []+llListReplaceList(aviScriptIndex, [1], idx, idx);
  1111. aviStatus = []+llListReplaceList(aviStatus, "", idx, idx);
  1112. SetScriptAlarm(idx, 0);
  1113. }
  1114. else if (cmd1 == "follow")
  1115. {
  1116. aviStatus = []+llListReplaceList(aviStatus, ["follow"], idx, idx);
  1117. if (cmd2=="me" || cmd2=="")
  1118. {
  1119. userData=llGetObjectDetails((key)sendUid, [OBJECT_NAME,OBJECT_POS, OBJECT_ROT]);
  1120. aviFollow = []+llListReplaceList(aviFollow, [(key)sendUid], idx, idx);
  1121. osNpcSay(uNPC, "Following you "+ llList2String(userData, 0));
  1122. }
  1123. else
  1124. {
  1125. key who = getAgentByName(cmd2);
  1126. if (who != NULL_KEY)
  1127. {
  1128. aviFollow = []+llListReplaceList(aviFollow, [who], idx, idx);
  1129. osNpcSay(uNPC, "Following " + cmd2);
  1130. }
  1131. }
  1132.  
  1133. }
  1134. else if (cmd1 == "set-state") // set a variable that indicates the current state of an NPC -- useful for scripts
  1135. {
  1136. aviScriptState= []+llListReplaceList(aviScriptState, [cmd2], idx, idx);
  1137. return 0;
  1138. }
  1139. else if (cmd1 == "debug")
  1140. {
  1141. integer dd = llList2Integer(aviScriptIndex, idx);
  1142. string scr;
  1143. if (dd >=0)
  1144. {
  1145. scr = GetScriptLine(llList2String(aviScriptText,idx) , dd-1);
  1146. }
  1147. llOwnerSay("Status="+llList2String(aviStatus, idx)+" node = "+llList2Integer(aviNodes, idx)+
  1148. " follow="+llList2String(aviFollow, idx)+" Alarm = "+(string)(llList2Integer(aviAlarm,idx)-llGetUnixTime())+
  1149. " scriptIndex="+llList2Integer(aviScriptIndex, idx)+" scriptText " +scr );
  1150. }
  1151. else if (cmd1 == "fly" && cmd2=="with") // "fly with me" "fly with Foo"
  1152. {
  1153. string who = llList2String(tokens, 6);
  1154. if (who == "me")
  1155. {
  1156. aviFollow = []+llListReplaceList(aviFollow, [(key)sendUid], idx, idx);
  1157. }
  1158. else
  1159. {
  1160. key w = getAgentByName(who);
  1161. if (w != NULL_KEY)
  1162. {
  1163. aviFollow = []+llListReplaceList(aviFollow, [w], idx, idx);
  1164.  
  1165. }
  1166. }
  1167. aviStatus = llListReplaceList(aviStatus, ["flyfollow"], idx, idx);
  1168. osNpcSay(uNPC, "Flying ");
  1169. }
  1170. else if (cmd1 == "leave")
  1171. {
  1172. // Start wandering between waypoints
  1173. osNpcStand(uNPC);
  1174. aviNodes = []+llListReplaceList(aviNodes, [GetNearestNode(osNpcGetPos(uNPC))], idx, idx);
  1175. aviStatus = []+llListReplaceList(aviStatus, ["wander"], idx, idx);
  1176. aviPrevNodes = []+llListReplaceList(aviPrevNodes, [-1], idx, idx);
  1177. }
  1178. else if (cmd1 == "flyaround")
  1179. {
  1180. // Start flying about between the waypoints in the "flyTargets" list -- useful for birds
  1181. aviStatus = []+llListReplaceList(aviStatus, ["godfly"], idx, idx);
  1182. osNpcSay(uNPC, "Flying like an eagle!!");
  1183.  
  1184. }
  1185. else if (cmd1 == "run-notecard")
  1186. {
  1187. // Run the script contained in the notecard <argument>
  1188. string stext= osGetNotecard(cmd2 );
  1189. aviStatus= []+llListReplaceList(aviStatus, "", idx, idx);
  1190. if (stext == "ERROR")
  1191. {
  1192. llOwnerSay("Notecard error "+cmd2);
  1193. return 1;
  1194. }
  1195. aviScriptText = []+llListReplaceList(aviScriptText, stext, idx, idx);
  1196. aviScriptIndex = []+llListReplaceList(aviScriptIndex, [1], idx, idx);
  1197. SetScriptAlarm(idx, 0);
  1198. }
  1199. else if (cmd1 == "stop-script")
  1200. {
  1201. // Stop executing the script and exit
  1202. aviScriptIndex = []+llListReplaceList(aviScriptIndex, [-1], idx, idx);
  1203. SetScriptAlarm(idx, 0);
  1204. }
  1205. else if (cmd1 == "dress")
  1206. {
  1207. string suff = "";
  1208. if (cmd2 != "") suff += "_"+cmd2;
  1209. string nm = llList2String(aviNames, idx);
  1210. llOwnerSay("Loading appearance "+"APP_"+nm+suff);
  1211. osNpcLoadAppearance(uNPC, "APP_"+nm+suff);
  1212. }
  1213. else if (cmd1 == "touch")
  1214. {
  1215. osNpcTouch(uNPC, (key)cmd2, LINK_ROOT);
  1216. }
  1217. else if (cmd1 == "seen")
  1218. {
  1219. integer i;
  1220. if (cmd2 == "all")
  1221. {
  1222. for (i=0; i < llGetListLength(seenArchive); i+=2)
  1223. osNpcSay(uNPC, "I saw "+ llList2String(seenArchive,i) + " " + TimeAgo(llList2Integer(seenArchive,i+1) ));
  1224. return 1;
  1225. }
  1226. else
  1227. {
  1228. for (i=0; i < llGetListLength(seenArchive); i+=2)
  1229. {
  1230. if (llSubStringIndex(llToLower(llList2String(seenArchive,i)), llToLower(cmd2))>=0)
  1231. {
  1232. osNpcSay(uNPC, "I saw "+ llList2String(seenArchive,i) + " around " + TimeAgo(llList2Integer(seenArchive,i+1) ));
  1233. return 1;
  1234. }
  1235. }
  1236. }
  1237. osNpcSay(uNPC, "I haven't seen "+ cmd2 + " around");
  1238. }
  1239. else if (cmd1 == "nearest")
  1240. {
  1241. integer n = GetNearestNode(osNpcGetPos(uNPC));
  1242. osNpcSay(uNPC, "Nearest waypoint is #"+n);
  1243. }
  1244. else if (llGetSubString(cmd1,0,0) == "@")
  1245. return 0;
  1246. else if (cmd1 != "")
  1247. {
  1248.  
  1249. {
  1250. if (llGetInventoryType(cmd1+".scr") == INVENTORY_NOTECARD)
  1251. {
  1252. ExecScriptLine(npcName , "run-notecard "+cmd1+".scr");
  1253. }
  1254. else
  1255. llMessageLinked(LINK_THIS, -1, inputString, uNPC);
  1256. }
  1257. }
  1258. return 1; // 1 means that wait until next timer tick for next notecard command
  1259. }
  1260.  
  1261. integer FindNewTarget(integer curNode, integer prevNode)
  1262. {
  1263. integer total=llGetListLength(wLinks);
  1264. candidateNode = [];
  1265. integer i;
  1266. integer a;
  1267. integer b;
  1268. for (i=0; i< total; i+=2)
  1269. {
  1270. a = llList2Integer(wLinks,i);
  1271. b = llList2Integer(wLinks,i+1);
  1272. if (a == curNode && prevNode != b) /// dont go back where we came from
  1273. candidateNode += b;
  1274. else if (b == curNode && prevNode !=a)
  1275. candidateNode += a;
  1276. }
  1277.  
  1278. integer l = llGetListLength(candidateNode);
  1279. if (l>0)
  1280. {
  1281. return llList2Integer(candidateNode, (integer)llFrand((float)l));
  1282. }
  1283. else
  1284. return prevNode; // go back to where we came from if there is no other option
  1285. }
  1286.  
  1287.  
  1288. integer MoveToNewTarget(integer idx)
  1289. {
  1290. integer curNode = llList2Integer(aviNodes,idx);
  1291. integer prevNode = llList2Integer(aviPrevNodes,idx);
  1292.  
  1293. key uuid = llList2Key(aviUids, idx);
  1294. if (uuid == NULL_KEY) return 1;
  1295. vector pos = osNpcGetPos(uuid);
  1296. osNpcStand(uuid);
  1297.  
  1298. vector wp = llList2Vector(wNodes, curNode);
  1299. float dist = llVecDist(pos, wp);
  1300. if (dist>10) osTeleportAgent(uuid, wp, <1,1, 7.1>);
  1301.  
  1302. integer nt = FindNewTarget(curNode, prevNode);
  1303. if (nt <0) return 0;
  1304. vector tgt = llList2Vector(wNodes, nt);
  1305. // Try to stay in the right 'lane'
  1306. vector rr = 0.5*llVecNorm(tgt - pos)*llEuler2Rot(<0,0,-PI/2>);
  1307. tgt += rr;
  1308. osSetSpeed(uuid, 1.0);
  1309. osNpcMoveToTarget(uuid, tgt, OS_NPC_NO_FLY);
  1310. SetScriptAlarm(idx, GetWalkTime( llVecDist(wp, tgt) )+4);
  1311. aviNodes = []+llListReplaceList(aviNodes, [nt], idx, idx);
  1312. aviPrevNodes = []+llListReplaceList(aviPrevNodes, [curNode], idx, idx);
  1313. return 0;
  1314. }
  1315.  
  1316.  
  1317. integer ExecScriptLine(string aviName, string scriptline)
  1318. {
  1319. // The token list expects the name of the avi twice. we use 0000 as the sending-uid identifier
  1320. string command = "! "+ (string)NULL_KEY +" " + aviName +" "+ aviName +" "+ scriptline;
  1321. // list tokens = llParseString2List(command, [" "], [] );
  1322. return ProcessNPCCommand(command);
  1323. }
  1324.  
  1325.  
  1326.  
  1327. string TimeAgo(integer time)
  1328. {
  1329. // time difference in seconds
  1330. integer now = llGetUnixTime();
  1331. integer timeDifference = now - time;
  1332. // small bug fix for when timeDifference is 0
  1333. if (timeDifference == 0)
  1334. return "just now";
  1335.  
  1336. list periods = ["second", "minute", "hour", "day", "week", "month", "year", "decade"];
  1337.  
  1338. //the number equivalent to periods
  1339. list lenghts = [1, 60, 3600, 86400, 604800, 2630880, 31570560, 315705600];
  1340.  
  1341. integer v = llGetListLength(lenghts) - 1;
  1342. integer no;
  1343.  
  1344. while((0 <= v) && (no = timeDifference/llList2Integer(lenghts, v) <= 1)) --v;
  1345. string output = llList2String(periods, v);
  1346.  
  1347. //this will get the correct time in periods, then divide the timeDifference
  1348. integer ntime = timeDifference / llList2Integer(lenghts, llListFindList(periods, [output]));
  1349.  
  1350. //if integer 'no' is not equal to 1 then it should have an s at the end
  1351. if(no != 1)
  1352. output += "s";
  1353.  
  1354. //This produces the finished output
  1355. output = (string)ntime + " "+ output + " ago";
  1356. return output;
  1357. }
  1358.  
  1359. giveCommands(integer n)
  1360. {
  1361. integer i;
  1362. string lstr = "";
  1363. string kstr = "";
  1364. list lnks;
  1365. for (i=0; i < llGetListLength(wayLinks); i+=2)
  1366. {
  1367. integer a = llList2Integer(wayLinks,i);
  1368. integer b = llList2Integer(wayLinks,i+1);
  1369. if (a == n)
  1370. {
  1371. lstr += (string)b+",";
  1372. lnks += (string)llList2Key(wayKeys,b);
  1373. }
  1374. else if (b == n)
  1375. {
  1376. lstr += (string)a+",";
  1377. lnks += (string)llList2Key(wayKeys,a);
  1378. }
  1379. }
  1380.  
  1381. string wstr = (string)n+"|SETDATA|"+vec2str(llList2Vector(wayPoints, n));
  1382. wstr += "|"+llList2String(wayNames, n)+"|"+lstr+"|0|"+llList2CSV(lnks);
  1383. //llOwnerSay(wstr);
  1384. llRegionSay(PEG_CHAN, wstr);
  1385. }
  1386.  
  1387.  
  1388.  
  1389. default
  1390. {
  1391.  
  1392. state_entry()
  1393. {
  1394. llSetText("NPCs", <1,1,1>,1.0);
  1395. llListenRemove(gListener);
  1396. gListener = llListen(channel, "", "", "");
  1397. llOwnerSay("Listening on channel "+channel);
  1398. ReloadConfig();
  1399. LoadMapData();
  1400. timerRuns=0;
  1401. RescanAvis();
  1402. greetedAvis = [];
  1403. scriptVars = [];
  1404.  
  1405. if (autoLoadOnReset)
  1406. {
  1407. llSleep(10);
  1408. doLoadAll();
  1409. llSleep(10); // Need to wait for their listeners attachments to start
  1410. doInitCmds();
  1411. llSleep(10);
  1412. }
  1413.  
  1414. llSetTimerEvent(TIMER_INTERVAL);
  1415. }
  1416.  
  1417. touch_start(integer num)
  1418. {
  1419.  
  1420. if (llDetectedKey(0) != llGetOwner()) return;
  1421. llDialog(llGetOwner(), "Welcome", menuItems, channel);
  1422. }
  1423.  
  1424.  
  1425. // This checks the statuses of all avis and performs commands accordingly
  1426. timer()
  1427. {
  1428. integer total = llGetListLength(aviUids);
  1429. integer g;
  1430. integer advanceScript;
  1431. list startedScripts = [];
  1432. if (curVisitors>0)
  1433. for (g=0; g < total ; g++)
  1434. {
  1435. advanceScript =0;
  1436. aviIndex = g;
  1437. npc = llList2Key(aviUids, g);
  1438. string status = llList2String(aviStatus, g);
  1439.  
  1440. if (status == "follow" || status == "flyfollow")
  1441. {
  1442. // This NPC is following someone
  1443. integer stat=llGetAgentInfo(npc);
  1444. if (stat & AGENT_SITTING)
  1445. {
  1446. // We 've been sat. stop following
  1447. return;
  1448. }
  1449.  
  1450. key who = llList2Key(aviFollow, g);
  1451. list userData = llGetObjectDetails(who, [OBJECT_POS, OBJECT_ROT]);
  1452. if (llGetListLength(userData) ==0)
  1453. {
  1454. // User left or died
  1455. aviStatus= []+llListReplaceList(aviStatus, [ "" ], g, g);
  1456. return;
  1457.  
  1458. }
  1459.  
  1460. rotation rot = llList2Rot(userData,1);
  1461. float ang = llFrand(1.0);
  1462. vector v = llList2Vector(userData,0) + <-1.9,0,0>*rot;
  1463. float dist = llVecDist(osNpcGetPos(npc), v);
  1464.  
  1465. if (status == "follow" && dist>50.)
  1466. {
  1467. osTeleportAgent(npc, v, <1,1,1>);
  1468. }
  1469. else if (dist>4)
  1470. {
  1471. //osNpcStopMoveToTarget(npc);
  1472. if (osIsNpc(who))
  1473. osSetSpeed(npc, .47);
  1474. else osSetSpeed(npc, 1.0);
  1475. if (status == "flyfollow")
  1476. osNpcMoveToTarget(npc, v+<0,0,2.>, OS_NPC_FLY );
  1477. else
  1478. osNpcMoveToTarget(npc, v, OS_NPC_NO_FLY );
  1479. }
  1480. }
  1481. else if (status == "wander")
  1482. {
  1483. if (llGetUnixTime() > llList2Integer(aviAlarm, g) +1)
  1484. {
  1485. integer curNode = llList2Integer(aviNodes, g);
  1486. integer i;
  1487. integer shouldMove =1;
  1488. llMessageLinked(LINK_THIS, -1, "WAYPOINT " + (string)curNode+" "+llList2String(aviNames, g), npc);
  1489. // avoid looping back to the same script while we are about to leave
  1490. if (llList2Integer(aviPrevNodes, g)>=0)
  1491. {
  1492. if (llListFindList(startedScripts, curNode)>=0)
  1493. {
  1494. // dont start the same script simultaneously
  1495. }
  1496. else
  1497. {
  1498. string ncName = "_"+curNode+".scr";
  1499. if (llGetInventoryType(ncName) == INVENTORY_NOTECARD)
  1500. {
  1501. startedScripts+= curNode;
  1502. ExecScriptLine(llList2String(aviNames, g), "run-notecard "+ncName);
  1503. shouldMove =0;
  1504. }
  1505. }
  1506. }
  1507.  
  1508. if (shouldMove>0)
  1509. {
  1510. MoveToNewTarget(g);
  1511. }
  1512. }
  1513. }
  1514. else if (status == "godfly")
  1515. {
  1516. // This NPC is flying around
  1517. if (llGetUnixTime() > llList2Integer(aviAlarm, g) +1)
  1518. {
  1519. vector nd = (vector)llList2String(flyTargets, (integer)llFrand(llGetListLength(flyTargets)));
  1520. integer flag = OS_NPC_FLY;
  1521. osSetSpeed(npc, 0.5);
  1522. integer theight = 10;
  1523. vector p = osNpcGetPos(npc);
  1524. SetScriptAlarm(g, GetWalkTime(llVecDist(p, nd))/2);
  1525. osNpcMoveToTarget(npc, nd + <llFrand(1),llFrand(1),theight>, flag);
  1526.  
  1527. }
  1528. }
  1529. else if (status == "pathf")
  1530. {
  1531. // Pathfinding - this NPC is following the path to a destination
  1532. integer avits = llList2Integer(aviAlarm, g);
  1533. if (llGetUnixTime() > avits)
  1534. {
  1535.  
  1536. vector p = osNpcGetPos(npc);
  1537. string path = llList2String(aviPath, g);
  1538. //llOwnerSay("Path="+path);
  1539. list pnodes = llParseString2List(path, [":"], []);
  1540. if (llGetListLength(pnodes)<1)
  1541. {
  1542. osNpcSay(npc, "Here we are");
  1543. aviStatus = []+llListReplaceList(aviStatus, [ "" ], g, g);
  1544. // continue the script (if any), since we reached our destination
  1545. SetScriptAlarm(g, 0);
  1546. }
  1547. else
  1548. {
  1549. integer nextTgt = llList2Integer(pnodes, 0);
  1550. string ndleft = ":"+llDumpList2String( llList2List(pnodes, 1, llGetListLength(pnodes)), ":");
  1551. aviPath = []+llListReplaceList(aviPath, [ ndleft ], g, g);
  1552. vector v = llList2Vector(wNodes, nextTgt);
  1553. SetScriptAlarm(g, GetWalkTime(llVecDist(p, v)));
  1554. osNpcMoveToTarget(npc, v + <llFrand(1.0),llFrand(1.0), 0.1> , OS_NPC_NO_FLY );
  1555. }
  1556. }
  1557. return;
  1558. }
  1559. else if (status == "prompt")
  1560. {
  1561. // do nothing
  1562. jump nexttick;
  1563. }
  1564.  
  1565.  
  1566. // Execute the next script line if a script is active
  1567. integer stopNow=0;
  1568. integer k;
  1569. integer scriptIndex = llList2Integer(aviScriptIndex, g);
  1570. while ( scriptIndex>0 && stopNow==0 && k++<5) // execute up to 10 lines at once if possible
  1571. {
  1572.  
  1573. //llOwnerSay("scriptIndex = "+ (string)scriptIndex);
  1574. integer tsAlarm = llList2Integer(aviAlarm, g);
  1575. if (tsAlarm >0 && llGetUnixTime() >= tsAlarm ) // The script should continue now
  1576. {
  1577. string scriptData = llList2String(aviScriptText, g);
  1578. string scriptline = GetScriptLine(scriptData, scriptIndex);
  1579. if (scriptline == "") // End of script
  1580. {
  1581. // This will prevent any further execution
  1582. aviScriptIndex = []+llListReplaceList(aviScriptIndex, [-1], g, g);
  1583. }
  1584. else
  1585. {
  1586. // Substitute sender with the prompt target, if any
  1587. string cmd = "! "+ (string)llList2Key(aviTarget, g) +" "+ llList2String(aviNames, g) +" "+ llList2String(aviNames, g) + " "+ scriptline;
  1588. stopNow = ProcessNPCCommand(cmd);
  1589. // Advance script pointer
  1590. scriptIndex = llList2Integer(aviScriptIndex, g);
  1591. aviScriptIndex = []+llListReplaceList(aviScriptIndex, [scriptIndex+1], g,g);
  1592. }
  1593. }
  1594. scriptIndex = llList2Integer(aviScriptIndex, g);
  1595. }
  1596.  
  1597. @nexttick;
  1598.  
  1599. llParticleSystem(
  1600. [
  1601. PSYS_SRC_PATTERN,PSYS_SRC_PATTERN_EXPLODE,
  1602. PSYS_SRC_BURST_RADIUS,0,
  1603. PSYS_SRC_ANGLE_BEGIN,0,
  1604. PSYS_SRC_ANGLE_END,0,
  1605. PSYS_SRC_TARGET_KEY,llGetKey(),
  1606. PSYS_PART_START_COLOR,<1.000000,0.000000,0.000000>,
  1607. PSYS_PART_END_COLOR,<1.000000,0.000000,0.000000>,
  1608. PSYS_PART_START_ALPHA,1,
  1609. PSYS_PART_END_ALPHA,0,
  1610. PSYS_PART_START_GLOW,0,
  1611. PSYS_PART_END_GLOW,0,
  1612. PSYS_PART_BLEND_FUNC_SOURCE,PSYS_PART_BF_SOURCE_ALPHA,
  1613. PSYS_PART_BLEND_FUNC_DEST,PSYS_PART_BF_ONE_MINUS_SOURCE_ALPHA,
  1614. PSYS_PART_START_SCALE,<0.500000,0.500000,0.000000>,
  1615. PSYS_PART_END_SCALE,<4.000000,4.000000,0.000000>,
  1616. PSYS_SRC_TEXTURE,"",
  1617. PSYS_SRC_MAX_AGE,0.5,
  1618. PSYS_PART_MAX_AGE,2,
  1619. PSYS_SRC_BURST_RATE,1,
  1620. PSYS_SRC_BURST_PART_COUNT,1,
  1621. PSYS_SRC_ACCEL,<0.000000,0.000000,0.000000>,
  1622. PSYS_SRC_OMEGA,<0.000000,0.000000,0.000000>,
  1623. PSYS_SRC_BURST_SPEED_MIN,0,
  1624. PSYS_SRC_BURST_SPEED_MAX,0,
  1625. PSYS_PART_FLAGS,
  1626. 0 |
  1627. PSYS_PART_EMISSIVE_MASK |
  1628. PSYS_PART_INTERP_COLOR_MASK |
  1629. PSYS_PART_INTERP_SCALE_MASK
  1630. ]);
  1631.  
  1632. }
  1633.  
  1634. timerRuns++;
  1635. if (timerRuns%20==0)
  1636. {
  1637. curVisitors = countVisitors();
  1638. }
  1639. }
  1640.  
  1641. listen(integer chan, string name, key id, string str) { // WARNING "id" is not the uid of the NPC-sender
  1642.  
  1643. string mes = str;
  1644. integer x = llSubStringIndex(str, " ");
  1645. if (x >=0) mes = llGetSubString(str, 0,x-1);
  1646.  
  1647. if (!(osIsNpc(llGetOwnerKey(id)) || llGetOwnerKey(id)==llGetOwner()))
  1648. {
  1649. llOwnerSay("Denied access to "+llKey2Name(id));
  1650. return;
  1651. }
  1652.  
  1653. //llOwnerSay("<<" + str);
  1654. if (mes == "!") // Something that has been sent from a Listener of attached to an NPC
  1655. {
  1656. ProcessNPCCommand(str);
  1657. return;
  1658. }
  1659. else if (mes =="FBALL")
  1660. {
  1661. // A poseball has been found. We have to check if it is transparent. If it is not, then we sit the NPC on it
  1662. list tok = llParseString2List(str, [" "] , [""]);
  1663. string npcname= llList2String( tok, 1);
  1664. integer idx = GetNPCIndex(npcname);
  1665. if (idx<0) return;
  1666. key unpc = llList2Key(aviUids, idx);
  1667. integer i;
  1668. key ball;
  1669. for (i=2; i < llGetListLength(tok);i++)
  1670. {
  1671. ball = llList2String(tok, i);
  1672. list prop = osGetPrimitiveParams(ball, [PRIM_COLOR, 0]); /// This only works we own the poseball
  1673. float alpha = 1.0;
  1674. if (llGetListLength(prop)>0) alpha = llList2Float(prop, 1);
  1675. if (alpha >0)
  1676. {
  1677. jump ballFound;
  1678. }
  1679. }
  1680. //llOwnerSay(npcname + ": All balls transparent");
  1681. @ballFound;
  1682. if (ball != NULL_KEY)
  1683. {
  1684. osNpcStand(unpc);
  1685. osNpcStopMoveToTarget(unpc);
  1686. osNpcSit(unpc, ball, OS_NPC_SIT_NOW);
  1687. aviStatus = []+llListReplaceList(aviStatus, ["sitting"], idx, idx);
  1688. }
  1689. }
  1690. else if (mes == "SETVAR")
  1691. {
  1692. list tok = llParseString2List(str, [" "] , [""]);
  1693. setVar(llList2String(tok,1), llList2String(tok,2));
  1694. }
  1695. else if (llGetSubString(mes, 0, 7) == "CLICKED|")// Message from map editor HUD
  1696. {
  1697. list ll = llParseString2List(str, ["|"] ,[]);
  1698. string cmd1 = llList2String(ll, 0);
  1699. integer num = llList2Integer(ll, 1);
  1700. if (curPoint!= num)
  1701. {
  1702. prevPoint = curPoint;
  1703. curPoint = num;
  1704. }
  1705.  
  1706. list btns = ["Close", "LinkPegs", "UnlinkPegs", "SetName"];
  1707. llDialog(llGetOwner(), "Current peg: "+ (string)curPoint+ " Previous: "+(string)prevPoint, btns, channel);
  1708. return;
  1709. }
  1710. else if (llGetSubString(mes, 0, 6) == "MRKKEY|")
  1711. {
  1712. list ll = llParseStringKeepNulls(str, ["|"] ,[]);
  1713. integer num = llList2Integer(ll, 1);
  1714. key k = llList2Key(ll, 2);
  1715. wayKeys = [] + llListReplaceList(wayKeys, [k], num,num);
  1716.  
  1717. }
  1718. else if (llGetSubString(mes, 0, 6) == "MARKER|")
  1719. {
  1720. list ll = llParseStringKeepNulls(str, ["|"] ,[]);
  1721. string cmd1 = llList2String(ll, 0);
  1722. integer num = llList2Integer(ll, 1);
  1723. vector pos = llList2Vector(ll, 2);
  1724. key tk = llList2Key(ll, 4);
  1725. wayPoints = llListReplaceList(wayPoints, [pos], num,num);
  1726.  
  1727. return;
  1728. }
  1729. else if (mes == "ShowPegDialog")
  1730. {
  1731. list btns = ["Close", "RezPegs", "SaveCards", "AddPeg", "DeletePeg", "LinkPegs", "UnlinkPegs", "ScanPegs", "ClearPegs", "SetName"];
  1732. llDialog(llGetOwner(), "First peg: "+ (string)curPoint+ " Second peg: "+(string)prevPoint, btns, 68);
  1733. return;
  1734. }
  1735.  
  1736.  
  1737. if (id != llGetOwner()) return; // Admin commands follow
  1738.  
  1739. if (mes == "SaveNPC")
  1740. {
  1741. llDialog(llGetOwner(), "Select NPC to save your appearance", llList2List(availableNames, 0,10)+ "more", channel);
  1742.  
  1743. userInputState = "WAIT_APPNAME";
  1744. }
  1745. else if (mes == "LoadNPC")
  1746. {
  1747. llDialog(llGetOwner(), "Select an NPC to load", llList2List(availableNames, 0,10)+"more", channel);
  1748. userInputState = "WAIT_AVINAME";
  1749. }
  1750. else if (mes == "RemoveNPC")
  1751. {
  1752. llDialog(llGetOwner(), "Select an NPC to delete", llList2List(availableNames, 0,10)+ "more", channel);
  1753. userInputState = "WAIT_REMOVEAVI";
  1754. }
  1755. else if (mes == "UpdateNPC")
  1756. {
  1757. llDialog(llGetOwner(), "Select an NPC to re-save appearance ", llList2List(availableNames, 0,10)+"more", channel);
  1758. userInputState = "WAIT_UPDATE";
  1759. }
  1760. else if (mes == "RemoveAll")
  1761. {
  1762. avis = osGetAvatarList();
  1763. llSay(0, llList2CSV(avis));
  1764. howmany = llGetListLength(avis);
  1765. integer i;
  1766. for (i =0; i < howmany; i+=3)
  1767. {
  1768. if (osIsNpc(llList2Key(avis, i)))
  1769. {
  1770. list p = llParseString2List(llKey2Name(llList2Key(avis,i)), [" "], []);
  1771. doRemoveNpc(llList2String(p, 0));
  1772. //osNpcStand(llList2Key(avis, i));
  1773. //osNpcRemove(llList2Key(avis, i));
  1774. }
  1775. }
  1776. aviUids = [];
  1777. aviNames = [];
  1778. }
  1779. else if (mes == "LoadAll")
  1780. {
  1781. llSetTimerEvent(0);
  1782. doLoadAll();
  1783. llSetTimerEvent(TIMER_INTERVAL);
  1784. }
  1785. else if (mes == "InitCmds")
  1786. {
  1787. llSetTimerEvent(0);
  1788. doInitCmds();
  1789. llSetTimerEvent(TIMER_INTERVAL);
  1790. }
  1791. else if (mes == "TimerOnOff")
  1792. {
  1793. timerRunning = !timerRunning;
  1794. llSetTimerEvent(TIMER_INTERVAL*timerRunning);
  1795. llOwnerSay("Timer="+(string)timerRunning);
  1796. }
  1797. else if (mes == "DumpData")
  1798. {
  1799. llOwnerSay("Names="+llList2CSV(aviNames));
  1800. llOwnerSay("Status="+llList2CSV(aviStatus));
  1801. llOwnerSay("Nodes="+llList2CSV(aviNodes));
  1802. llOwnerSay("PrevNodes="+llList2CSV(aviPrevNodes));
  1803. llOwnerSay("ScriptIndex="+llList2CSV(aviScriptIndex));
  1804. llOwnerSay("Alarm="+llList2CSV(aviAlarm));
  1805. llOwnerSay("Curvisitors="+(string)(curVisitors)+ " Timer=" +timerRunning+" timerRuns="+(string)timerRuns);
  1806. llOwnerSay("Vars="+llList2CSV(scriptVars));
  1807. }
  1808. else if (mes == "ReConfig")
  1809. {
  1810. ReloadConfig();
  1811. LoadMapData();
  1812. }
  1813. else if (mes == "deflectTo")
  1814. {
  1815. list tok = llParseString2List(str, [" "] , [""]);
  1816. deflectToNode = GetNodeIndexByName(llToLower(llList2String(tok,1)));
  1817. llOwnerSay("Deflecting to #"+(string)deflectToNode);
  1818. }
  1819. else if (mes == "AddPeg")
  1820. {
  1821. vector v = llGetPos();
  1822. list res = llGetObjectDetails(llGetOwner(), [OBJECT_POS]);
  1823. wayPoints += llList2Vector(res, 0);
  1824. llOwnerSay("Added point " + (string)(llGetListLength(wayPoints)));
  1825. llRezObject("peg", v, ZERO_VECTOR, ZERO_ROTATION, llGetListLength(wayPoints)-1);
  1826. giveCommands( llGetListLength(wayPoints)-1);
  1827. return;
  1828. }
  1829. else if (mes == "LinkPegs")
  1830. {
  1831.  
  1832. integer i;
  1833. for (i=0; i < llGetListLength(wayLinks); i+=2)
  1834. {
  1835. integer a = llList2Integer(wayLinks,i);
  1836. integer b = llList2Integer(wayLinks,i+1);
  1837. if ((a == curPoint && b == prevPoint ) || (b == curPoint && a== prevPoint ))
  1838. {
  1839. llOwnerSay("Link exists");
  1840. return;
  1841. }
  1842. }
  1843. wayLinks += curPoint;
  1844. wayLinks += prevPoint;
  1845. giveCommands(curPoint);
  1846. giveCommands(prevPoint);
  1847. }
  1848. else if (mes == "UnlinkPegs")
  1849. {
  1850.  
  1851. integer i;
  1852. for (i=0; i < llGetListLength(wayLinks); i+=2)
  1853. {
  1854. integer a = llList2Integer(wayLinks,i);
  1855. integer b = llList2Integer(wayLinks,i+1);
  1856. if ((a == curPoint && b == prevPoint ) || (b == curPoint && a== prevPoint ))
  1857. {
  1858. wayLinks = llListReplaceList(wayLinks, [], i, i+1);
  1859. giveCommands(a);
  1860. giveCommands(b);
  1861. }
  1862. }
  1863. }
  1864. else if (mes == "ClearPegs")
  1865. {
  1866. llRegionSay(PEG_CHAN, "die");
  1867. }
  1868. else if (mes == "ScanPegs")
  1869. {
  1870. llOwnerSay("Scanning pegs ordered");
  1871. llRegionSay(PEG_CHAN, "REPORT");
  1872. }
  1873. else if (mes == "SetName")
  1874. {
  1875. llTextBox(llGetOwner(), "Set Peg #"+(string)curPoint + " name to: ", channel);
  1876. userInputState="WAIT_PEGNAME";
  1877. }
  1878. else if (mes == "RezPegs")
  1879. {
  1880. list lines = llParseString2List(osGetNotecard("__waypoints"), ["\n"], []);
  1881. integer i;
  1882. wayPoints =[];
  1883. wayNames = [];
  1884. for (i=0; i < llGetListLength(lines); i++)
  1885. {
  1886. list line = llParseString2List(llList2String(lines, i), [","], []);
  1887. vector v = < llList2Float(line, 0), llList2Float(line, 1), llList2Float(line, 2) >;
  1888. string nname = llList2String(line, 3);
  1889. if (v != ZERO_VECTOR)
  1890. {
  1891. wayPoints += v;
  1892. wayNames += nname;
  1893. }
  1894. }
  1895. wayLinks = llParseString2List( llStringTrim(osGetNotecard("__links"), STRING_TRIM) , ["\n", ","], [" "]);
  1896. llOwnerSay(llList2CSV(wayLinks));
  1897. llRegionSay(PEG_CHAN, "die");
  1898. llSleep(0.5);
  1899. vector pos = llGetPos();
  1900. for (i=0; i < llGetListLength(wayPoints); i++)
  1901. llRezObject("peg", pos, ZERO_VECTOR, ZERO_ROTATION, i);
  1902. llSleep(0.5);
  1903. for (i=0; i < llGetListLength(wayPoints); i++)
  1904. giveCommands(i);
  1905. }
  1906. else if (mes == "UpdatePegs")
  1907. {
  1908. integer i;
  1909. for (i=0; i < llGetListLength(wayPoints); i++)
  1910. giveCommands(i);
  1911. }
  1912. else if (mes == "SaveCards")
  1913. {
  1914. integer i=0;
  1915. string scriptText = "";
  1916. if (llGetListLength(wayLinks)==0)
  1917. {
  1918. llOwnerSay("No links created! Not saving cards!");
  1919. return;
  1920. }
  1921. for (i=0; i < llGetListLength(wayPoints); i++)
  1922. {
  1923. vector v = llList2Vector(wayPoints,i);
  1924. scriptText += (string)v.x+","+(string)v.y+","+(string)v.z + "," + llList2String(wayNames, i) + "\n";
  1925. }
  1926.  
  1927. string cardName = "__waypoints";
  1928. if (llGetInventoryType(cardName)==INVENTORY_NOTECARD)
  1929. {
  1930. llRemoveInventory(cardName);
  1931. llSleep(0.5);
  1932. }
  1933. osMakeNotecard(cardName,scriptText);
  1934. llOwnerSay(cardName +" Saved");
  1935. cardName = "__links";
  1936. if (llGetInventoryType(cardName)==INVENTORY_NOTECARD)
  1937. {
  1938. llRemoveInventory(cardName);
  1939. llSleep(0.5);
  1940. }
  1941. scriptText = "";
  1942. for (i=0; i < llGetListLength(wayLinks); i+=2)
  1943. scriptText += llList2String(wayLinks,i)+ ","+llList2String(wayLinks,i+1)+ ",\n";
  1944. osMakeNotecard(cardName,scriptText);
  1945. llOwnerSay(cardName +" Saved");
  1946. llSleep(1);
  1947. LoadMapData();
  1948. }
  1949. else if (userInputState != "" && mes != "")// Process dialog commands
  1950. {
  1951. if (mes == "more")
  1952. {
  1953. llDialog(llGetOwner(), "Select an NPC", llList2List(availableNames, 11,-1), channel);
  1954. }
  1955. else
  1956. {
  1957. if (userInputState == "WAIT_APPNAME")
  1958. {
  1959. osAgentSaveAppearance(llGetOwner(), "APP_"+llToLower(mes));
  1960. llSay(0, "Saved Appearance " + llGetOwner() + " -> APP_"+llToLower(mes));
  1961. }
  1962. else if (userInputState == "WAIT_PEGNAME")
  1963. {
  1964. wayNames = [] + llListReplaceList(wayNames, [llStringTrim(mes, STRING_TRIM)],curPoint, curPoint);
  1965. giveCommands(curPoint);
  1966. llOwnerSay("Waypoint " +(string)curPoint+ " name='"+mes+"'");
  1967. }
  1968. else if (userInputState == "WAIT_AVINAME")
  1969. {
  1970. doLoadNPC(mes, GetLastName(mes));
  1971.  
  1972. }
  1973. else if (userInputState == "WAIT_UPDATE")
  1974. {
  1975. integer idx = GetNPCIndex(mes);
  1976. if (idx >=0)
  1977. {
  1978. key uu = llList2Key(aviUids, idx);
  1979. osNpcSaveAppearance(uu, "APP_"+llToLower(mes));
  1980. llOwnerSay("Updating APP_"+llToLower(mes) );
  1981. }
  1982. else llOwnerSay("Not found "+mes);
  1983. }
  1984. else if (userInputState == "WAIT_REMOVEAVI")
  1985. {
  1986. doRemoveNpc(mes);
  1987. }
  1988.  
  1989. userInputState="";
  1990. }
  1991. }
  1992. }
  1993.  
  1994.  
  1995. link_message(integer lnk, integer num, string command, key npc) // This script is in the object too.
  1996. {
  1997. if (num != -1) // -1 means we sent it
  1998. {
  1999. ProcessNPCCommand(command);
  2000. }
  2001. }
  2002.  
  2003. changed(integer change)
  2004. {
  2005. if (change & (CHANGED_REGION_START | CHANGED_OWNER | CHANGED_REGION))
  2006. {
  2007. llResetScript();
  2008. }
  2009. }
  2010.  
  2011. }
  2012.  
  2013.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement