xs_egg.lsl 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892
  1. // :CATEGORY:XS Pet
  2. // :NAME:XS Pet Robot
  3. // :AUTHOR:Ferd Frederix
  4. // :KEYWORDS: Pet,XS,breed,breedable,companion,Ozimal,Meeroo,Amaretto,critter,Fennux,Pets
  5. // :CREATED:2013-09-06
  6. // :EDITED:2014-07-15
  7. // :ID:988
  8. // :NUM:1448
  9. // :REV:0.53
  10. // :WORLD:Second Life, OpenSim
  11. // :DESCRIPTION:
  12. // XS Pet xs_egg
  13. // :CODE:
  14. // xs_egg
  15. // this egg script will color a 2-prim egg when rezzed.
  16. // When born from a pet, it will accept a new pet and egg from the Mama.
  17. // The only thing ever needed to start with in an egg is this script , as it get the rest of the contents from the egg crate or Mama.
  18. // 11-30-2012 added AUTO_HATCH variable. If set to TRUE, rthe egg will auto-hatch when laid. Default: FALSE. If FALSE, you have to touch and hatch the egg manually
  19. // 4-10-2013 V 0.43 Lots of casting to fix Opensim 0.7.4 failures to parse llList2Float and llList2Integer when there are strings in the list
  20. // Version 0.45 7-31-2013 List2Float and list2Integer do not parse strings in Opensim worlds the same. Converted in xs_egg and xs_eggcup
  21. // 0.53 07-15-2014 bug in init - did not switch to state state rezzed;
  22. /// tunables:
  23. string SPECIAL = "Normal"; // change this to trigger the xs_special script in the pet. See xs_special documentation in the pet
  24. vector Position = <0.0, 0.0, 0.25>; // how far above the egg to rez the pet.
  25. vector Rot = <0,0,0>; // the rotation of the pet when rezzed
  26. integer AUTO_HATCH = FALSE; //If set to TRUE, rthe egg will auto-hatch when laid. Default: FALSE. If FALSE, you have to touch and hatch the egg manually
  27. // START OF COPIED file 'Global Constants.txt' from the Debug folder. It has to be the same in all files
  28. // If you change this in any script, change it in all of them, please. It works a lot better that way.
  29. // This is code based on Version 0.50 01-30-2014
  30. // For version history, see file revisions.txt
  31. //
  32. // LICENSE
  33. /////////////////////////////////////////////////////////////////////
  34. // This code is licensed as Creative Commons Attribution/NonCommercial/Share Alike
  35. // See http://creativecommons.org/liceses/by-nc-sa/3.0/
  36. // Noncommercial -- You may not use this work for commercial purposes, i.e., you cannot sell this script in any form, including derivatives.
  37. // If you alter, transform, or build upon this work, you may distribute the resulting work only under the same or similar license to this one.
  38. // This means that you cannot sell this or derivative code by itself, but you may share and use this code in any object or virtual world.
  39. // You must attribute authorship in the original scripts to Ferd Frederix and Xundra Snowpaw, and leave this notice intact.
  40. // You do not have to give back to the community any changes you make, however, code changes would be greatly appreciated!
  41. //
  42. // Exception: I am allowing this script to be used in an original build and sold with the build.
  43. // You are not selling the script, you are selling the build. If you want to sell these scripts, write your own or use the original at http://code.google.com/p/xspets/
  44. // Note: Xundra Snowpaw's license was 'New BSD' license and adding additional licenses is allowed.
  45. // Based on code from Xundra Snowpaw
  46. // New BSD License: http://www.opensource.org/licenses/bsd-license.php
  47. // Copyright (c) 2010, Xundra Snowpaw
  48. // All rights reserved.
  49. // Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
  50. //* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  51. //* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer
  52. // in the documentationand/or other materials provided with the distribution.
  53. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
  54. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
  55. // BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  56. // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  57. // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  58. // EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  59. ////////////////////////////////////////////////////////////////////
  60. // DEBUG - lets you see and hear wtf is happening
  61. integer debug = FALSE; // set to TRUE TO hear a lot of chat
  62. // This section has a few tuneable items that MUST be changed for any new pet
  63. // SECURITY
  64. string SECRET_PASSWORD = "top secret string"; // must use a password unique to any species of animal, when ENCRYPT= TRUE. Otherwise you will find Pet type A fucking pet type B.
  65. integer SECRET_NUMBER = 99999; // any number thats a secret, not necessary to change usually, this is used when pets are born and eggs are rezzed to establish a comm channel.
  66. integer ENCRYPT = TRUE; // set to TRUE to encrypt all data, Some Opensim worlds prefer FALSE due to parsing bugs, TRUE is the most secure. If FALSE you MUST change the FOOD_CHANNEL and other channels for different pets. or they will literally fuck each other.
  67. // if you add the UUID for your avatar here, you can change it later
  68. // and other alts or friends can change it too, and all of you can work on these pets.
  69. // If you leave it blank, only the creator of the root prim can work on these pets.
  70. key YOUR_UUID = "";
  71. // PET NAMES - YOU MUST CHANGE THEM HERE AND IN THE ROOT PRIM OF THE OBJECT - THEY MUST MATCH EXACTLY
  72. /////////////////////////
  73. string MaleName = "Troubot"; // Must be the name of your animal
  74. string FemaleName = "Troubot"; // The name of the female pet, if a different shape or prim count. Can be the same as the Male for pets like the robot that are unisex.
  75. string Egg = "Nut and Bolt"; // was 'XS Egg', must be the name of your egg
  76. string Crate = "Transport Spaceship"; // was XS-Cryocrate, must be the name of the crate you package pets in
  77. string HomeObject = "Home Flag"; // was "XS Home Object", must be the name of your Home Post indicator
  78. string EggCup = "Toolbox"; // was "XS Egg Cup", must be the name of your egg holder
  79. // any other object names are 'do not cares'.
  80. // NOTHING NEEDS TO BE CHANGED BELOW, BUT CAN BE CHANGED IF YOU DO IT EVERYWHERE
  81. // misc tunables
  82. float GROWTH_AMOUNT = 0.10; // 10% size increase each day for MaxAge days = 200% (double size after 7 days)
  83. integer MaxAge = 7; // stop growing in seven days. 10% growth compounded daily means that your pet will be 194% larger ( 2x, basically) in 7 days.
  84. integer UNITS_OF_FOOD = 168; // food bowl food qty, used by food bowl only
  85. float secs_to_grow = 86400; // grow daily = 86400 seconds
  86. float FOOD_BOWL_SCAN_INTERVAL = 1800.0; // look for food every 3 hours
  87. float fPregnancy = 172800.0; // how many seconds to lay an egg = 2 days or 48 hours.
  88. float MALE_TIMEOUT = 900.0 ; // in seconds, female waits this long in one spot for a male to arrive
  89. float SEX_WAIT = 10800.0; // How often they desire sex = 3 hours
  90. float fDaysToAdult = 7; // 7 days to become old enough to breed.
  91. integer SECONDS_BETWEEN_FOOD_NORMAL = 14400; // number of seconds to get hungry = 4 hours
  92. integer SECONDS_BETWEEN_FOOD_HUNGRY = 3600; // number of seconds before hunger count increases = 1 hour
  93. integer MAXIMUM_HUNGER = 30; // They die after a month with no food.
  94. // I control versions by Subversion Source Code Control. But the updater needs a version numbert in world.
  95. // This is the Protocol version. If you change this, then all pets with a lower version will be updated by the updater
  96. float VERSION = 0.50;
  97. // the leg sizes are safe to leave alone or set to 0 if you use a thin base prim, these are from the original Quail
  98. float LegLength = 0.064; // length of pet leg??? - not sure
  99. float LegOffset = 0.052399; // This is added to the Post Z to position the pet
  100. // the following are global constants and do not need to be changed
  101. // Prim animation linkmessages are sent by scripts on Link Message number 1
  102. // The strings are the names of the animations that are recorded.
  103. // No need to change them unless you want to change names of the animations when you run the prim animator, or you add additional link messages
  104. // If your pet walks, you need to record these names and save them in the notecard
  105. //
  106. // Example:
  107. // llMessageLinked(LINK_SET, LINK_ANIMATE, ANI_STAND, "");
  108. // The above line will play the pre-recorded 'stand up' animation "stand" using the animator script.
  109. // The following animations are used in the pet. You can add your own.
  110. string ANI_STAND = "stand"; // default standing animation
  111. string ANI_WALKL = "left"; // triggers Left foot and Right arm walk animation
  112. string ANI_WALKR = "right"; // triggers Right foot and Left arm walk animation
  113. string ANI_SLEEP = "sleep"; // Sleeping
  114. string ANI_WAVE = "wave"; // Calling for sex, needs help with food, etc.
  115. // Channel assignments
  116. // if you change any of these constants, change it everywhere and in the list in XS_Debug so it can print them
  117. // If you turn encryption FALSE, you MUST change these between species of pets are they will fuck with each other. Literally.
  118. integer FOOD_CHANNEL = -999191;
  119. integer ANIMAL_CHANNEL = -999192;
  120. integer EGG_CHANNEL = -999193;
  121. integer HOME_CHANNEL = -999194;
  122. integer BOX_CHANNEL = -999195;
  123. integer ACC_CHANNEL = -999196;
  124. integer UPDATE_CHANNEL = -999197;
  125. integer API_CHANNEL = -999198;
  126. // global link messages to control the animal, never any need to change these.
  127. // They are exposed here so they will be the same everywhere. This uses a bit of RAM, but who cares?
  128. integer LINK_ANIMATE = 1; // messages on num 1 are assumed to be directed at the prim animator.
  129. integer DECREASE_FOOD = 100; // used in the food bowl.
  130. integer LINK_COLOR1_GET = 101; // to xs_egg color plugin.
  131. integer LINK_COLOR2_GET = 102; // to xs_egg color plugin.
  132. integer LINK_COLOR1_PUT = 103; // to xs_egg color plugin.
  133. integer LINK_COLOR2_PUT = 104; // to xs_egg color plugin.
  134. integer LINK_AGE_START = 800; // when pety is rezzed and secret_number is sent by brain to breeder, eater and infomatic get booted up
  135. integer LINK_TEXTURE = 801; // ask for a new texture, or paint a color
  136. integer LINK_BREEDNAME = 802; // the name of the pet texture from the texture server notecard
  137. integer LINK_FOOD_CONSUME = 900; // from movement to brain when close to food, brain then consumes a random amount up to 10000
  138. integer LINK_FOODMINUS = 901; // xs_brain receives FOOD_CONSUME, decrement hunger (eat)
  139. integer LINK_HUNGRY = 903; // sent by eater (string)hunger_amount, checks each hour
  140. integer LINK_HAMOUNT = 904; // hunger_amount = (integer)str,m updates the hunger amount in scripts
  141. integer LINK_SET_HOME = 910; // loc ^ dist
  142. integer LINK_MOVER = 911; // tell mover to rest for str seconds
  143. integer LINK_FOODIE_CLR = 920; // clear all food_bowl_keys and contents
  144. integer LINK_FOODIE = 921; // send FOOD_LOCATION coordinates to movement
  145. integer LINK_COLOR1 = 930; // colour1
  146. integer LINK_COLOR2 = 931; // colour2
  147. integer LINK_SEX = 932; // sex
  148. integer LINK_SHINE = 933; // shine
  149. integer LINK_GLOW = 934; // glow
  150. integer LINK_GEN = 935; // generation
  151. integer LINK_RESET_SIZE = 936; // reset size to 1
  152. integer LINK_MAGE = 940; // xs_brain sends, xs_ager consumes, adds str to age, if older than 7 days, will grow the animal
  153. integer LINK_DAYTIME = 941; // xs_ager consumes, starts a timer of 86,400 seconds in xs_ager
  154. integer LINK_GET_AGE = 942; // get age from xs_ager and sent it on channel 943
  155. integer LINK_PUT_AGE = 943; // print age from xs_ager
  156. integer LINK_PACKAGE = 950; // look for a cryo_crate
  157. integer LINK_SEEK_FEMALE = 960; // MALE_BREED_CALL
  158. integer LINK_MALE_BREED_CALL = 961; // triggered by LINK_SEEK_FEMALE
  159. integer LINK_SIGNAL_ELIGIBLE = 962; // sent by female when hears LINK_MALE_BREED_CALL
  160. integer LINK_FEMALE_ELIGIBLE = 963; // sent when it hears in chat FEMALE_ELIGIBLE
  161. integer LINK_CALL_MALE = 964; // if LINK_FEMALE_ELIGIBLE && looking_for_female
  162. integer LINK_MALE_ON_THE_WAY = 965; // triggered by LINK_CALL_MALE
  163. integer LINK_FEMALE_LOCATION = 966; // female location, sends coordinates of a female
  164. integer LINK_RQST_BREED = 967; // sent when close enough to male/female
  165. integer LINK_CALL_MALE_INFO = 968; // sent by xs_breeding, this line of code was in error in v.24 of xs_breeding see line 557 and 636 of xs_brain which make calls and also xs_breeding which receives LINK_MALE_INFO.
  166. integer LINK_MALE_INFO = 969; // Breeding failed, sent info
  167. integer LINK_LAY_EGG = 970; // Rez Object(Egg...
  168. integer LINK_BREED_FAIL = 971; // key = father, failed, timed out
  169. integer LINK_PREGNANT = 972; // chick is preggers
  170. integer LINK_SOUND_OFF= 974; // sound is off
  171. integer LINK_SOUND_ON= 973; // sound is on
  172. integer LINK_SLEEPING = 990; // close eyes
  173. integer LINK_UNSLEEPING = 991; // open eyes
  174. integer LINK_SOUND = 1001; // plays a sound if enabled
  175. integer LINK_SPECIAL = 1010; // xs_special, if str = "Normal", removes script
  176. integer LINK_EFFECTS_ON = 2000; // particle effects in the packger
  177. integer LINK_PREGNANCY_TIME = 5000; // in seconds as str
  178. integer LINK_SLEEP = 7999; // disable sleep by parameter
  179. integer LINK_TIMER = 8000; // scan for food bowl about every 1800 seconds
  180. integer LINK_DIE = 9999; // death
  181. string Copyright = " (c)2014 by Ferd Frederix"; // You cannot change this line, but you can change the code that prints it!
  182. // See License agreements above.
  183. // Attribution is required, as these files are copyrighted.
  184. DEBUG ( string msg){
  185. if (debug) {
  186. llOwnerSay(llGetScriptName() + ":" + msg);
  187. }
  188. }
  189. ///////// end global Link constants ////////
  190. // END OF COPIED CODE
  191. // DON'T CHANGE THE FOLLOWING! (Unless you know what you are doing!)
  192. integer XTEA_DELTA = 0x9E3779B9; // (sqrt(5) - 1) * 2^31
  193. integer xtea_num_rounds = 6;
  194. list xtea_key = [0, 0, 0, 0];
  195. integer hex2int(string hex) {
  196. if(llGetSubString(hex,0,1) == "0x")
  197. return (integer)hex;
  198. if(llGetSubString(hex,0,0) == "x")
  199. return (integer)("0"+hex);
  200. return(integer)("0x"+hex);
  201. }
  202. // Convers any string to a 32 char MD5 string and then to a list of
  203. // 4 * 32 bit integers = 128 bit Key. MD5 ensures always a specific
  204. // 128 bit key is generated for any string passed.
  205. list xtea_key_from_string( string str )
  206. {
  207. str = llMD5String(str,0); // Use Nonce = 0
  208. return [ hex2int(llGetSubString( str, 0, 7)),
  209. hex2int(llGetSubString( str, 8, 15)),
  210. hex2int(llGetSubString( str, 16, 23)),
  211. hex2int(llGetSubString( str, 24, 31))];
  212. }
  213. // Encipher two integers and return the result as a 12-byte string
  214. // containing two base64-encoded integers.
  215. string xtea_encipher( integer v0, integer v1 )
  216. {
  217. integer num_rounds = xtea_num_rounds;
  218. integer sum = 0;
  219. do {
  220. // LSL does not have unsigned integers, so when shifting right we
  221. // have to mask out sign-extension bits.
  222. v0 += (((v1 << 4) ^ ((v1 >> 5) & 0x07FFFFFF)) + v1) ^ (sum + llList2Integer(xtea_key, sum & 3));
  223. sum += XTEA_DELTA;
  224. v1 += (((v0 << 4) ^ ((v0 >> 5) & 0x07FFFFFF)) + v0) ^ (sum + llList2Integer(xtea_key, (sum >> 11) & 3));
  225. } while( num_rounds = ~-num_rounds );
  226. //return only first 6 chars to remove "=="'s and compact encrypted text.
  227. return llGetSubString(llIntegerToBase64(v0),0,5) +
  228. llGetSubString(llIntegerToBase64(v1),0,5);
  229. }
  230. // Decipher two base64-encoded integers and return the FIRST 30 BITS of
  231. // each as one 10-byte base64-encoded string.
  232. string xtea_decipher( integer v0, integer v1 )
  233. {
  234. integer num_rounds = xtea_num_rounds;
  235. integer sum = XTEA_DELTA*xtea_num_rounds;
  236. do {
  237. // LSL does not have unsigned integers, so when shifting right we
  238. // have to mask out sign-extension bits.
  239. v1 -= (((v0 << 4) ^ ((v0 >> 5) & 0x07FFFFFF)) + v0) ^ (sum + llList2Integer(xtea_key, (sum>>11) & 3));
  240. sum -= XTEA_DELTA;
  241. v0 -= (((v1 << 4) ^ ((v1 >> 5) & 0x07FFFFFF)) + v1) ^ (sum + llList2Integer(xtea_key, sum & 3));
  242. } while ( num_rounds = ~-num_rounds );
  243. return llGetSubString(llIntegerToBase64(v0), 0, 4) +
  244. llGetSubString(llIntegerToBase64(v1), 0, 4);
  245. }
  246. // Encrypt a full string using XTEA.
  247. string xtea_encrypt_string( string str )
  248. {
  249. if (! ENCRYPT)
  250. return str;
  251. // encode string
  252. str = llStringToBase64(str);
  253. // remove trailing =s so we can do our own 0 padding
  254. integer i = llSubStringIndex( str, "=" );
  255. if ( i != -1 )
  256. str = llDeleteSubString( str, i, -1 );
  257. // we don't want to process padding, so get length before adding it
  258. integer len = llStringLength(str);
  259. // zero pad
  260. str += "AAAAAAAAAA=";
  261. string result;
  262. i = 0;
  263. do {
  264. // encipher 30 (5*6) bits at a time.
  265. result += xtea_encipher(llBase64ToInteger(llGetSubString(str, i, i + 4) + "A="), llBase64ToInteger(llGetSubString(str, i+5, i + 9) + "A="));
  266. i+=10;
  267. } while ( i < len );
  268. return result;
  269. }
  270. // Decrypt a full string using XTEA
  271. string xtea_decrypt_string( string str ) {
  272. if (! ENCRYPT)
  273. return str;
  274. integer len = llStringLength(str);
  275. integer i=0;
  276. string result;
  277. //llOwnerSay(str);
  278. do {
  279. integer v0;
  280. integer v1;
  281. v0 = llBase64ToInteger(llGetSubString(str, i, i + 5) + "==");
  282. i+= 6;
  283. v1 = llBase64ToInteger(llGetSubString(str, i, i + 5) + "==");
  284. i+= 6;
  285. result += xtea_decipher(v0, v1);
  286. } while ( i < len );
  287. // Replace multiple trailing zeroes with a single one
  288. i = llStringLength(result) - 1;
  289. while ( llGetSubString(result, i - 1, i) == "AA" ){
  290. result = llDeleteSubString(result, i, i);
  291. i--;
  292. }
  293. i = llStringLength(result) - 1;
  294. // while (llGetSubString(result, i, i + 1) == "A" ) {
  295. // i--;
  296. // }
  297. result = llGetSubString(result, 0, i+1);
  298. i = llStringLength(result);
  299. integer mod = i%4; //Depending on encoded length diffrent appends are needed
  300. if(mod == 1) result += "A==";
  301. else if(mod == 2 ) result += "==";
  302. else if(mod == 3) result += "=";
  303. return llBase64ToString(result);
  304. }
  305. string base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  306. // EGG code begins again, see tunables up above
  307. integer unpackaged = FALSE; // Opensim has issues with establishing a on_rez, so we use a timer to fix the bug
  308. // breedable params
  309. vector colour1;
  310. vector colour2;
  311. integer sex;
  312. integer gen;
  313. integer shine;
  314. float glow;
  315. // globals
  316. string colourName1; // new string to hold color name version 0.52
  317. string colourName2;
  318. integer api_listener; // holds the API listener id so we can remove it
  319. integer locked; // only hear 1 PONG from a crate
  320. integer owner_touch; // flag set when ower has touched the prim
  321. integer menu_listener; // integer of the listener so we can remove it.
  322. // allow either a UUID to be entered, or not, and still maintain security
  323. integer CheckPerms()
  324. {
  325. if (YOUR_UUID != "" && llGetOwner() != YOUR_UUID)
  326. return 1;
  327. if (llGetOwner() != llGetCreator())
  328. return 1;
  329. return 0;
  330. }
  331. set_colours(vector c1, vector c2, integer shine, float glow)
  332. {
  333. // set the root prim (the egg top), skip the base, and then do the egg bottom half
  334. // Link order is top Egg half, Base, then bottom of the egg half
  335. // IN CASE YOU ARE USING THE TEXTURE PLUG IN:
  336. string msg = (string) c1 + "^" +
  337. (string) c2 + "^" +
  338. "0^" + // sex is unknown in an egg
  339. (string) shine + "^" +
  340. (string) glow + "^";
  341. llMessageLinked(LINK_SET,LINK_TEXTURE,msg,NULL_KEY); // tell the optional texture plugin to fetch the textures
  342. llSetPrimitiveParams([PRIM_COLOR, ALL_SIDES, c2, 1.0, PRIM_BUMP_SHINY, ALL_SIDES, shine, PRIM_BUMP_NONE, PRIM_GLOW, ALL_SIDES, glow]);
  343. llSetLinkPrimitiveParams(2, [PRIM_COLOR, ALL_SIDES, c1, 1.0, PRIM_BUMP_SHINY, ALL_SIDES, shine, PRIM_BUMP_NONE, PRIM_GLOW, ALL_SIDES, glow]);
  344. llMessageLinked(LINK_SET,LINK_COLOR1_GET,(string) colour1,""); // V 0.52 send colors to plug in
  345. llMessageLinked(LINK_SET,LINK_COLOR2_GET,(string) colour2,"");
  346. }
  347. say_details()
  348. {
  349. string myshine;
  350. if (shine == 0) {
  351. myshine = "None";
  352. } else
  353. if (shine == 1) {
  354. myshine = "Low";
  355. } else
  356. if (shine == 2) {
  357. myshine = "Medium";
  358. } else
  359. if (shine == 3) {
  360. myshine = "High";
  361. }
  362. llWhisper(0, "Color: " + colourName1);
  363. llWhisper(0, "Color: " + colourName2);
  364. llWhisper(0, "Shine: " + myshine);
  365. llWhisper(0, "Glow: " + (string)((integer)(glow * 100)) + "%");
  366. llWhisper(0, "Special: " + SPECIAL);
  367. llWhisper(0, "Generation: " + (string)gen);
  368. llSay(API_CHANNEL, "XSPet^" + (string)llGetKey() + "^" + (string)colour1 + "^" + (string)colour2 + "^" + (string)shine + "^" + (string)glow + "^" + SPECIAL + "^" + (string)gen + "^XSPetEnd");
  369. }
  370. default
  371. {
  372. state_entry()
  373. {
  374. DEBUG("RESET");
  375. llSetText("", <1,1,1>, 1.0); // no white text
  376. llSetColor(<1,1,1>, ALL_SIDES); // all white egg
  377. llSetLinkColor(2, <1,1,1>, ALL_SIDES); // white egg link 2
  378. llParticleSystem([]); // no particles, beats me why, somebody once had an egg that spewed so I am leaving it.
  379. xtea_key = xtea_key_from_string(SECRET_PASSWORD);
  380. }
  381. // the egg accepts inventory from crates and mama
  382. changed(integer change) {
  383. if (change & CHANGED_ALLOWED_DROP) {
  384. if (llGetInventoryType(FemaleName) != INVENTORY_NONE && llGetInventoryType(MaleName) != INVENTORY_NONE && llGetInventoryType(Egg) != INVENTORY_NONE) {
  385. llAllowInventoryDrop(FALSE);
  386. }
  387. }
  388. }
  389. on_rez(integer param)
  390. {
  391. DEBUG("REZZING");
  392. llSetText("Rezzing...", <1,0,0>, 1.0); // Rez Rezzing.. text
  393. // if param = 0, then someone rezzed an egg. It had better be the creator or someone who has put their UUID in the script.
  394. // all colors start in GEN 0 as primary colors here
  395. if (param == 0) {
  396. DEBUG("CREATOR REZZED ME");
  397. if (! CheckPerms() ) {
  398. integer colour = (integer)llFrand(9.0) + 1;
  399. if (colour == 1) {
  400. colour1 = <1,0,0>; // red/red
  401. colour2 = <1,0,0>;
  402. } else
  403. if (colour == 2) {
  404. colour1 = <1,0,0>; // red/blue
  405. colour2 = <0,1,0>;
  406. } else
  407. if (colour == 3) {
  408. colour1 = <1,0,0>; // red/blue
  409. colour2 = <0,0,1>;
  410. } else
  411. if (colour == 4) {
  412. colour1 = <0,1,0>; // green/red
  413. colour2 = <1,0,0>;
  414. } else
  415. if (colour == 5) {
  416. colour1 = <0,1,0>; // blue/blue
  417. colour2 = <0,1,0>;
  418. } else
  419. if (colour == 6) {
  420. colour1 = <0,1,0>; // green/blue
  421. colour2 = <0,0,1>;
  422. } else
  423. if (colour == 7) {
  424. colour1 = <0,0,1>; // blue/red
  425. colour2 = <1,0,0>;
  426. } else
  427. if (colour == 8) {
  428. colour1 = <0,0,1>; // blue/red
  429. colour2 = <0,1,0>;
  430. } else
  431. if (colour == 9) {
  432. colour1 = <0,0,1>; // blue/blue
  433. colour2 = <0,0,1>;
  434. }
  435. set_colours(colour1, colour2, shine, glow);
  436. state rezzed;
  437. } else {
  438. llWhisper(0, "Oh no! This " + Egg + " was broken in your inventory! Please use an " + Egg + " container next time.");
  439. state dead;
  440. }
  441. } else if (param == SECRET_NUMBER) {
  442. DEBUG("REZZING from an object");
  443. menu_listener = llListen(EGG_CHANNEL, "", "", "");
  444. if ( CheckPerms() ) {
  445. llAllowInventoryDrop(TRUE);
  446. }
  447. unpackaged = TRUE;
  448. llSetTimerEvent(5);
  449. }
  450. }
  451. link_message(integer sender_number, integer number, string message, key id)
  452. {
  453. if (number == LINK_COLOR1_PUT)
  454. {
  455. colourName1 = message;
  456. } else if (number == LINK_COLOR2_PUT)
  457. {
  458. colourName2 = message;
  459. state rezzed;
  460. }
  461. }
  462. listen(integer channel, string sender, key id, string msg) {
  463. list data = llParseString2List(xtea_decrypt_string(msg), ["^"], []);
  464. if (llList2String(data, 0) == "XSPET" && (key) llList2String(data, 1) == llGetKey()) {
  465. if (llList2String(data, 2) == "UNBOX") {
  466. colour1 = (vector)llList2String(data, 3);
  467. colour2 = (vector)llList2String(data, 4);
  468. gen = (integer) llList2String(data,5);
  469. shine = (integer) llList2String(data, 6);
  470. glow = (float) llList2String(data, 7);
  471. SPECIAL = llList2String(data, 8);
  472. llListenRemove(menu_listener);
  473. set_colours(colour1, colour2, shine, glow);
  474. } else
  475. if (llList2String(data, 2) == "BORN") {
  476. vector fcolour1 = (vector)llList2String(data, 3);
  477. vector fcolour2 = (vector)llList2String(data, 4);
  478. integer fgen = (integer) llList2String(data,5);
  479. integer fshine = (integer) llList2String(data, 6);
  480. float fglow = (float) llList2String(data, 7);
  481. integer fglow_gene = (integer) llList2String(data, 8);
  482. vector mcolour1 = (vector)llList2String(data, 9);
  483. vector mcolour2 = (vector)llList2String(data, 10);
  484. integer mgen = (integer) llList2String(data, 11);
  485. integer mshine = (integer)llList2String(data, 12);
  486. float mglow = (float) llList2String(data, 13);
  487. integer mglow_gene = (integer)llList2String(data, 14);
  488. integer mix = (integer)llFrand(2) + 1;
  489. float deviation1 = (llFrand(10) - 5) / 100;
  490. float deviation2 = (llFrand(10) - 5) / 100;
  491. if (mix == 1) {
  492. colour1.x = (fcolour1.x / 2 + mcolour1.x / 2) + deviation1;
  493. colour1.y = (fcolour1.y / 2 + mcolour1.y / 2) + deviation1;
  494. colour1.z = (fcolour1.z / 2 + mcolour1.z / 2) + deviation1;
  495. colour2.x = (fcolour2.x / 2 + mcolour2.x / 2) + deviation2;
  496. colour2.y = (fcolour2.y / 2 + mcolour2.y / 2) + deviation2;
  497. colour2.z = (fcolour2.z / 2 + mcolour2.z / 2) + deviation2;
  498. } else {
  499. colour1.x = (fcolour1.x / 2 + mcolour2.x / 2) + deviation1;
  500. colour1.y = (fcolour1.y / 2 + mcolour2.y / 2) + deviation1;
  501. colour1.z = (fcolour1.z / 2 + mcolour2.z / 2) + deviation1;
  502. colour2.x = (fcolour2.x / 2 + mcolour1.x / 2) + deviation2;
  503. colour2.y = (fcolour2.y / 2 + mcolour1.y / 2) + deviation2;
  504. colour2.z = (fcolour2.z / 2 + mcolour1.z / 2) + deviation2;
  505. }
  506. if (colour1.x < 0)
  507. colour1.x = 0;
  508. if (colour1.x > 1)
  509. colour1.x = 1;
  510. if (colour1.y < 0)
  511. colour1.y = 0;
  512. if (colour1.y > 1)
  513. colour1.y = 1;
  514. if (colour1.z < 0)
  515. colour1.z = 0;
  516. if (colour1.z > 1)
  517. colour1.z = 1;
  518. if (colour2.x < 0)
  519. colour2.x = 0;
  520. if (colour2.x > 1)
  521. colour2.x = 1;
  522. if (colour2.y < 0)
  523. colour2.y = 0;
  524. if (colour2.y > 1)
  525. colour2.y = 1;
  526. if (colour2.z < 0)
  527. colour2.z = 0;
  528. if (colour2.z > 1)
  529. colour2.z = 1;
  530. if (mgen > fgen) {
  531. gen = mgen + 1;
  532. } else {
  533. gen = fgen + 1;
  534. }
  535. // TODO: shine / glow
  536. shine = 0;
  537. if (gen > 2) {
  538. integer pos = (integer)llFrand(100) + 1;
  539. if (fshine == mshine && fshine > 0) {
  540. if (pos < 25) {
  541. shine = fshine + 1;
  542. if (shine > 3) {
  543. shine = 3;
  544. }
  545. }
  546. } else {
  547. if (pos < 10) {
  548. // increase shine
  549. if (mshine > fshine) {
  550. shine = mshine + 1;
  551. } else
  552. if (fshine > mshine) {
  553. shine = fshine + 1;
  554. } else {
  555. shine = 1;
  556. }
  557. if (shine > 3) {
  558. shine = 3;
  559. }
  560. }
  561. }
  562. }
  563. glow = 0.0;
  564. if (mglow <= 0.3 && fglow <= 0.3) {
  565. if (mglow > fglow) {
  566. glow = mglow - 0.1;
  567. } else if (fglow > mglow) {
  568. glow = fglow - 0.1;
  569. }
  570. }
  571. if (fglow_gene >= 10 && mglow_gene >= 10) {
  572. integer poss = (integer)llFrand(100) + 1;
  573. if (poss < 25) {
  574. glow = 0.3;
  575. }
  576. } else if (fglow_gene >= 10 || mglow_gene >= 10) {
  577. integer poss = (integer)llFrand(100) + 1;
  578. if (poss < 10) {
  579. glow = 0.3;
  580. }
  581. }
  582. llListenRemove(menu_listener);
  583. set_colours(colour1, colour2, shine, glow);
  584. llSetTimerEvent(1.0);
  585. }
  586. }
  587. }
  588. timer() {
  589. if (unpackaged)
  590. {
  591. DEBUG("UNPACKAGED");
  592. llSay(ANIMAL_CHANNEL, xtea_encrypt_string("XSPET^EGG_READY^" + (string)llGetKey() + "^SMILE")); // tell Mama she has a baby
  593. llSay(BOX_CHANNEL, xtea_encrypt_string("XSPET^" + (string)llGetKey() + "^EGG_READY^SMILE")); // and tell a crate it is okay to poof
  594. unpackaged = FALSE;
  595. return;
  596. }
  597. DEBUG("TIMER EXPIRED");
  598. if (llGetInventoryType(MaleName) != INVENTORY_NONE && llGetInventoryType(FemaleName) != INVENTORY_NONE && llGetInventoryType(Egg) != INVENTORY_NONE) {
  599. state rezzed;
  600. }
  601. }
  602. }
  603. state rezzed
  604. {
  605. on_rez(integer param)
  606. {
  607. DEBUG("STATE REZZED ON_REZ");
  608. if (CheckPerms()) {
  609. llWhisper(0, "Oh no! This " + Egg + " was broken in your inventory! Please use an " + Egg + " container next time.");
  610. state dead;
  611. }
  612. }
  613. state_entry()
  614. {
  615. DEBUG("STATE REZZED STATE ENTRY");
  616. if (SPECIAL == "Normal") {
  617. llSetText("", <1,1,1>, 1.0);
  618. } else {
  619. llSetText(SPECIAL, <1,1,1>, 1.0);
  620. }
  621. api_listener = llListen(API_CHANNEL, "", "", "");
  622. // added auto hatch operator 11-30-2012 fkb
  623. if (AUTO_HATCH && unpackaged)
  624. state hatching; }
  625. touch_start(integer num)
  626. {
  627. owner_touch = 0;
  628. say_details();
  629. if (llDetectedKey(0) == llGetOwner()) {
  630. owner_touch = 1;
  631. integer chan = (integer)llFrand(100000.0) + 1000;
  632. menu_listener = llListen(chan, "", llGetOwner(), "");
  633. llDialog(llGetOwner(), "I'm a " + Egg + ". What would you like to do with me?", ["Hatch", "Package", "Nothing"], chan);
  634. }
  635. llSetTimerEvent(30.0);
  636. }
  637. timer()
  638. {
  639. DEBUG("TIMER EXPIRED");
  640. llSetTimerEvent(0);
  641. if (owner_touch == 1) {
  642. llOwnerSay("Menu timeout.");
  643. llListenRemove(menu_listener);
  644. owner_touch = 0;
  645. }
  646. }
  647. listen(integer channel, string sender, key id, string msg)
  648. {
  649. if (channel == API_CHANNEL) {
  650. list data = llParseString2List(msg, ["^"], []);
  651. if ((llList2String(data, 0) == MaleName || llList2String(data, 0) == FemaleName) && (key) llList2String(data, 1) == llGetKey()) {
  652. say_details();
  653. }
  654. } else {
  655. if (id == llGetOwner()) {
  656. llSetTimerEvent(0);
  657. llListenRemove(menu_listener);
  658. if (msg == "Hatch") {
  659. state hatching;
  660. } else
  661. if (msg == "Package") {
  662. state package;
  663. }
  664. }
  665. }
  666. }
  667. state_exit() {
  668. llListenRemove(api_listener);
  669. }
  670. }
  671. state hatching
  672. {
  673. state_entry()
  674. {
  675. DEBUG("STATE HATCHING");
  676. sex = (integer)llFrand(2) + 1;
  677. if (sex == 1)
  678. llRezObject(MaleName, llGetPos() + Position, ZERO_VECTOR, llGetRot() * llEuler2Rot(Rot * DEG_TO_RAD) , SECRET_NUMBER);
  679. else
  680. llRezObject(FemaleName, llGetPos() + Position, ZERO_VECTOR, llGetRot() * llEuler2Rot(Rot * DEG_TO_RAD) , SECRET_NUMBER);
  681. }
  682. object_rez(key id)
  683. {
  684. DEBUG("OBJECT REZZED");
  685. menu_listener = llListen(EGG_CHANNEL, "", id, "");
  686. }
  687. listen(integer channel, string sender, key id, string msg)
  688. {
  689. list decrypted = llParseString2List(xtea_decrypt_string(msg), ["^"], []);
  690. if (llList2String(decrypted, 0) == "XSPET" && llList2String(decrypted, 1) == "READY" && llList2String(decrypted, 2) == (string)id) {
  691. llGiveInventory(id, MaleName);
  692. llGiveInventory(id, FemaleName);
  693. llGiveInventory(id, Egg);
  694. string sexname;
  695. if (sex == 1)
  696. sexname = MaleName;
  697. else
  698. sexname = FemaleName;
  699. llSay(ANIMAL_CHANNEL, xtea_encrypt_string("XSPET^CONFIG^" + (string)id + "^" + (string)colour1 + "^" + (string)colour2 + "^" + (string)sex + "^" + (string)shine + "^" + (string)glow + "^" + (string)gen + "^0^0^" + sexname + "^0^" + SPECIAL));
  700. llDie();
  701. }
  702. }
  703. }
  704. state package
  705. {
  706. state_entry() {
  707. DEBUG("STATE PACKAGED");
  708. llSetTimerEvent(20.0);
  709. llWhisper(0, "Looking for a " + Egg + " container...");
  710. menu_listener = llListen(EGG_CHANNEL, "", "", "");
  711. llSay(BOX_CHANNEL, xtea_encrypt_string("XSPET^" + (string)llGetKey() + "^CUP_PING^" + (string)VERSION));
  712. }
  713. timer()
  714. {
  715. DEBUG("TIMER EXPIRED");
  716. llListenRemove(menu_listener);
  717. llSetTimerEvent(0);
  718. llWhisper(0, "No " + Egg + " container found.");
  719. state rezzed;
  720. }
  721. listen(integer channel, string sender, key id, string msg)
  722. {
  723. list data = llParseString2List(xtea_decrypt_string(msg), ["^"], []);
  724. if (llList2String(data, 0) == "XSPET" && (key) llList2String(data, 1) == llGetKey() && llList2String(data, 2) == "CUP_PONG" && llList2Float(data, 3) >= VERSION && locked == 0) {
  725. llSay(BOX_CHANNEL, xtea_encrypt_string("XSPET^" + (string)id + "^" + (string)colour1 + "^" + (string)colour2 + "^" + (string)shine + "^" + (string)glow + "^" + (string)gen + "^" + SPECIAL));
  726. locked = 1;
  727. } else
  728. if (llList2String(data, 0) == "XSPET" && llList2Key(data, 1) == llGetKey() && llList2String(data, 2) == "CUP_DIE") {
  729. llDie();
  730. }
  731. }
  732. }
  733. state dead
  734. {
  735. state_entry()
  736. {
  737. llSetText("Broken " + Egg, <1,0,0>, 1.0);
  738. }
  739. }