Flight script.lsl 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. // :CATEGORY:Bird
  2. // :NAME:flamingo
  3. // :AUTHOR:Ferd Frederix
  4. // :KEYWORDS:
  5. // :CREATED:2013-09-06
  6. // :EDITED:2014-09-24
  7. // :ID:314
  8. // :NUM:418
  9. // :REV:1
  10. // :WORLD:Second Life
  11. // :DESCRIPTION:
  12. // Flying script
  13. // :CODE:
  14. // Bird flock flight script
  15. // Author: Ferd Frederix
  16. // This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
  17. // This means that this script itself is not for sale, that the script must be full Mod at all time, and that modifications to it MUST be provided to anyone upon request. Pets made with this script may be sold. ~ Ferd Frederix
  18. // 5-26-2013
  19. // requires the following animations, use the names on the right
  20. string sLand = "land"; // land is when the legs are down
  21. string sFly = "fly"; // fly is legs up
  22. string sPeck = "peck"; // peck is actual pecking at the ground
  23. string sPeckL = "peckL"; // peckL is left side pecking at the ground
  24. string sPeckR = "peckR"; // peckR is right side pecking at the ground
  25. string sLegFlop = "legs"; // legs is heads up
  26. string sLookAround = "look";// looking around, with a wing flap
  27. string sLanding = "landing";// landing positions
  28. integer _debug = FALSE; // to see what happens, set to FALSE for normal operation
  29. float FUDGE = 0.0; // random delay in flight speed each span travlled
  30. float SPEED = 2.0; // how fast to fly, large = faster, in meters per second.
  31. float RANGE = 10; // how far to sense avatars before flying
  32. float TIMEOUT = 5; // how long to stay on ground after flight, and to scan for avatars
  33. float MIN = 3; // minimum time between animations
  34. float MAX = 7; // MAX + MIN (3+7=10) is the maximum pause between animations
  35. integer channel = -325238; // Change this only if you want flocks to not fly unless a sensor in this species detects a human. Otherwise any species will set off flight in 100 meter distance.
  36. string PECK = "pecking"; // peck sound
  37. string FLAP = "flying-dragon"; // flying wing sound, used here when the wings flap idly
  38. string IDLE = "flamingo"; // a sound of a bunch of flamingos
  39. string FLYING = "flamingo honking"; // used randomly in flight
  40. // Link message numbers to/from the main bird menu
  41. integer fromRoot = -3500;
  42. integer toRoot = -3501;
  43. integer toFlight = -3502;
  44. float totalTime; // the total time it takes to fly around once.
  45. list lCoordinate; // a list of coordinates, rotations, and times from the recorder
  46. // boolean flags
  47. integer iStopMoving; // we need to stop moving
  48. integer iAmFlying = FALSE; // true if we are flying.
  49. integer iStartTimer = FALSE; // true once the timer is set up
  50. integer iStarted = FALSE; // true once someone has clicked Start
  51. // movement
  52. integer iAmMaster ; // true if we are the controlling bird
  53. vector startPos; // Home pos
  54. vector vLastRelPos; // last position we read
  55. rotation lastRot; // last rotation
  56. rotation startRot; // initial rotation
  57. integer listener; // listener int
  58. rotation NormRot(rotation Q)
  59. {
  60. float MagQ = llSqrt(Q.x*Q.x + Q.y*Q.y +Q.z*Q.z + Q.s*Q.s);
  61. return <Q.x/MagQ, Q.y/MagQ, Q.z/MagQ, Q.s/MagQ>;
  62. }
  63. DEBUG(string msg)
  64. {
  65. if (_debug)
  66. llOwnerSay(msg);
  67. }
  68. restart()
  69. {
  70. SetupListens();
  71. vLastRelPos = ZERO_VECTOR;
  72. startRot = llGetRot();
  73. iAmFlying = FALSE;
  74. if (iStarted)
  75. {
  76. llSetTimerEvent(llFrand(MAX)+MIN); // movement channel
  77. }
  78. }
  79. menu()
  80. {
  81. llDialog(llGetOwner(),"Bird Controls:",["Start","-","Stop","Set Home","-","Setup"],channel);
  82. }
  83. startFlight()
  84. {
  85. DEBUG("flying");
  86. // tell the others to boot up
  87. if (iAmMaster)
  88. llShout(channel,"Start");
  89. llMessageLinked(LINK_SET,1,sFly,"");
  90. iStartTimer = TRUE;
  91. llSetTimerEvent (0.1);
  92. }
  93. SetupListens()
  94. {
  95. if (listener)
  96. llListenRemove(listener);
  97. listener = llListen(channel,"","","");
  98. }
  99. default
  100. {
  101. on_rez(integer p)
  102. {
  103. llResetScript(); // only if not recrded
  104. }
  105. state_entry()
  106. {
  107. startPos = llGetPos();
  108. startRot = llGetRot();
  109. llStopSound();
  110. llSetKeyframedMotion([],[KFM_COMMAND,KFM_CMD_STOP]);
  111. llMessageLinked(LINK_SET,1,sLand,"");
  112. llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_PHYSICS_SHAPE_TYPE, PRIM_PHYSICS_SHAPE_CONVEX]); // needed for older clients
  113. vLastRelPos = ZERO_VECTOR;
  114. llMessageLinked(LINK_SET,0,"Setup","");
  115. totalTime = 0;
  116. }
  117. link_message(integer sender_number, integer number, string message, key id)
  118. {
  119. DEBUG("Bird herd:" +(string) number + ":" + message );
  120. if (number == toFlight) // coordinates
  121. {
  122. list lLine = llParseString2List(message, ["|"], []);
  123. DEBUG(llDumpList2String(lLine,","));
  124. vector pos = (vector) llList2String(lLine,0);
  125. if (pos != ZERO_VECTOR)
  126. {
  127. rotation rot = (rotation) llList2String(lLine,1);
  128. float distance = llVecDist(pos,vLastRelPos);
  129. DEBUG("Dist:" + (string) distance);
  130. float time = distance / SPEED;
  131. DEBUG("T1:" + (string) time);
  132. time += llFrand(FUDGE);
  133. // there is a minimum time
  134. if (time < .2)
  135. time = 0.2;
  136. //time = (float) ((integer) (time * 45) /45); // round off to nearest frame time to stop drift
  137. DEBUG("T2:" + (string) time);
  138. lCoordinate += pos ; //* newRot;
  139. lCoordinate += NormRot(rot);
  140. lCoordinate += time;
  141. totalTime += time;
  142. // update the position so we can tell the difference for time calcs
  143. vLastRelPos = pos;
  144. lastRot = rot;
  145. }
  146. }
  147. else if (message == "Playback")
  148. {
  149. llSetPos(startPos);
  150. llSetRot(startRot);
  151. llOwnerSay("Route saved");
  152. llOwnerSay("Flight time is " + (string) totalTime + " seconds.");
  153. state movement;
  154. }
  155. }
  156. }
  157. state movement
  158. {
  159. state_entry()
  160. {
  161. llSetSoundQueueing(TRUE);
  162. restart();
  163. menu();
  164. }
  165. link_message(integer sender_number, integer number, string message, key id)
  166. {
  167. DEBUG("Bird herd:" +(string) number + ":" + message );
  168. }
  169. sensor(integer number)
  170. {
  171. if (iAmMaster && ! iAmFlying)
  172. {
  173. startFlight();
  174. }
  175. }
  176. touch_start(integer p)
  177. {
  178. if (llDetectedKey(0) == llGetOwner())
  179. {
  180. menu();
  181. }
  182. }
  183. timer()
  184. {
  185. if (iStartTimer)
  186. {
  187. llMessageLinked(LINK_SET,1,sFly,"");
  188. llSleep(1); // time for the prims to move into place
  189. iAmFlying = TRUE;
  190. iStartTimer = FALSE;
  191. llSetKeyframedMotion(lCoordinate, [KFM_DATA, KFM_TRANSLATION|KFM_ROTATION, KFM_MODE, KFM_FORWARD]);
  192. llSetTimerEvent(totalTime); // wake us up at end of the trip.
  193. DEBUG("Started flying");
  194. }
  195. else if (iAmFlying)
  196. {
  197. DEBUG("Stopping");
  198. llSetKeyframedMotion([],[KFM_COMMAND,KFM_CMD_STOP]);
  199. llMessageLinked(LINK_SET,1,sLanding,"");
  200. llSleep(1); // time to land, flapping motion
  201. llMessageLinked(LINK_SET,1,sLand,"");
  202. llSetPos(startPos);
  203. llSetRot(startRot);
  204. llStopSound();
  205. iAmFlying = FALSE;
  206. DEBUG("stopped");
  207. llSetTimerEvent(llFrand(MAX)+MIN);
  208. llSensorRepeat("", "", AGENT, RANGE, PI, TIMEOUT);
  209. }
  210. else
  211. {
  212. DEBUG("peck");
  213. float rand = llFrand(10);
  214. if (rand < 1.0) // 10 % chance of peck right
  215. {
  216. llMessageLinked(LINK_ROOT,1,sPeckR,"");
  217. llPlaySound(PECK,1);
  218. }
  219. else if (rand < 2.0) // 10 % chance of a peck to the left {
  220. {
  221. llMessageLinked(LINK_ROOT,1,sPeckL,"");
  222. llPlaySound(PECK,1);
  223. }
  224. else if (rand < 4.0) // 20% chance of a peck
  225. {
  226. llMessageLinked(LINK_SET,1,sPeck,"");
  227. llPlaySound(PECK,1);
  228. }
  229. else if (rand < 6.0) // 20% chance of a leg swap
  230. {
  231. llMessageLinked(LINK_SET,1,sLegFlop,"");
  232. }
  233. else if (rand < 8.0) // 20 % chance of a look around && flap
  234. {
  235. llMessageLinked(LINK_ROOT,1,sFly,""); // wings out, flapping
  236. llMessageLinked(LINK_ROOT,1,sLookAround,""); // heads up
  237. llPlaySound(IDLE,1); // make honking sounds
  238. llSleep(2);
  239. llMessageLinked(LINK_ROOT,1,sLand,""); // back to idle
  240. }
  241. else // 20%
  242. {
  243. if (iAmMaster) // only the lead bird loops the honking
  244. {
  245. llPlaySound(IDLE,1);
  246. }
  247. }
  248. llSetTimerEvent(llFrand(MAX)+MIN);
  249. }
  250. // they clicked stop, but we were flying, so we shut down here
  251. if (iStopMoving)
  252. {
  253. llSensorRemove();
  254. llSetTimerEvent(0.0);
  255. iStopMoving = FALSE;
  256. }
  257. } // timer
  258. listen(integer channel, string name, key id, string message)
  259. {
  260. if (message == "sensor")
  261. {
  262. iAmMaster = FALSE;
  263. llSensorRemove();
  264. }
  265. else if ( message == "Setup")
  266. {
  267. state default;
  268. }
  269. else if (message == "Stop")
  270. {
  271. if (iAmFlying)
  272. iStopMoving = TRUE; // cannot stop timer when flying, so we signal instead
  273. else
  274. llSetTimerEvent(0);
  275. llSensorRemove();
  276. }
  277. else if (message == "Start")
  278. {
  279. if (iAmFlying)
  280. return;
  281. iStarted = TRUE;
  282. llSleep(llFrand(1.0));
  283. startFlight();
  284. }
  285. else if (message == "Set Home")
  286. {
  287. if (iAmFlying)
  288. return;
  289. startPos = llGetPos();
  290. startRot = llGetRot();
  291. llOwnerSay("Position set");
  292. }
  293. }
  294. on_rez(integer p)
  295. {
  296. llShout(channel,"sensor");
  297. iAmMaster = TRUE;
  298. restart();
  299. }
  300. }