====== Myriad Lite Character Designer ====== INCOMPLETE // Myriad_Lite_Character_Designer-v0.0.0-20131219.lsl // Copyright (c) 2013 by Allen Kerensky (OSG/SL) All Rights Reserved. // This work is dual-licensed under // Creative Commons Attribution (CC BY) 3.0 Unported // http://creativecommons.org/licenses/by/3.0/ // - or - // Modified BSD License (3-clause) // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // * Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // * Neither the name of Myriad Lite nor the names of its contributors may be // used to endorse or promote products derived from this software without // specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN // NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // The Myriad RPG System was designed, written, and illustrated by Ashok Desai // Myriad RPG System licensed under: // Creative Commons Attribution (CC BY) 2.0 UK: England and Wales // http://creativecommons.org/licenses/by/2.0/uk/ // CONSTANTS - DO NOT CHANGE DURING RUN string BASENAME = "Myriad Lite Character Designer"; // base name of this script without version or date string VERSION = "0.0.1"; // Allen Kerensky's script version string VERSIONDATE = "20131219"; // Allen Kerensky's script yyyymmdd // CHARACTER DESIGNER STORAGE list PRIMNAMES; list CATEGORIES = [ "NAMES","NIKCNAMES","TITLES","FACTIONS","SPECIES","BACKGROUNDS","CAREERS", "STATISTICS","RESILIENCES","BOONS","FLAWS","SKILLS","EFFECTS","STUNTS","QUOTES","ITEMS" ]; integer NUMCAT; // number of category in CATEGORIES list string CURCAT; // name of current category integer NUMITEM; // number of item in current REGION_LIST string CURITEM; // name of current item in current category list integer MY_DYN; // the character designer dynamic channel integer MY_HAND; // the character designer dynamic channel handle integer MENU_DYN; // the character designer dialogs dynamic channel integer MENU_HAND; // the character designer dialogs dynamic channel handle string REQUEST; // current request to dispatch // REGION SETTING SERVER STORAGE integer REGION_DYN; // the region server dynamic channel integer REGION_HAND; // the region server dynamic channel handle list REGION_LIST; // CSV list of items in current category - requested from region setting server // PLAYER STORAGE integer PLAYER_DYN; // the player's HUD dynamic channel integer PLAYER_HAND; // the player HUD dynamic channel handle key WHO; // who is using the setup list PLAYER_LIST; // list of player attributes in current aspect/category BUY_ITEM() { } COMMAND(string in) { if ( in == "BUTTON_NEW" ) { if ( REQUEST == "NAMES" ) { SET_NAME(); return; } if ( REQUEST == "NICKNAMES" ) { SET_NICKNAME(); return; } if ( REQUEST == "TITLES" ) { SET_TITLE(); return; } if ( REQUEST == "FACTIONS" ) { SET_FACTION(); return; } } REQUEST=in; if ( in == "NAMES" ) { GET_NAME(WHO); return; } if ( in == "NICKNAMES" ) { GET_NICKNAME(WHO); return; } if ( in == "TITLES" ) { GET_TITLE(WHO); return; } if ( in == "FACTIONS" ) { GET_FACTION(WHO); return; } // locate category name from list if ( llListFindList(CATEGORIES,[in]) != -1 ) { CURCAT = in; NUMITEM = 0; UPDATE(); llRegionSay(REGION_DYN,"LIST_"+CURCAT); return; } if ( in == "FIRST_CATEGORY") { FIRST_CATEGORY(); return;} if ( in == "FIRST_ITEM" ) { FIRST_ITEM(); return; } if ( in == "PREV_CATEGORY" ) { PREV_CATEGORY(); return; } if ( in == "PREV_ITEM" ) { PREV_ITEM(); return; } if ( in == "NEXT_CATEGORY" ) { NEXT_CATEGORY(); return; } if ( in == "NEXT_ITEM" ) { NEXT_ITEM(); return; } if ( in == "LAST_CATEGORY" ) { LAST_CATEGORY(); return; } if ( in == "LAST_ITEM" ) { LAST_ITEM(); return; } if ( in == "BUY ITEM" ) { BUY_ITEM(); return; } if ( in == "SELL ITEM" ) { SELL_ITEM(); return; } if ( in == "RESET" ) { RESET(); return; } if ( in == "SAVE" ) { SAVE(); return; } } FIRST_CATEGORY() { NUMCAT = 0; CURCAT = llList2String(CATEGORIES,NUMCAT); NUMITEM = 0; llRegionSay(REGION_DYN,"LIST_"+CURCAT); } FIRST_ITEM() { NUMITEM = 0; CURITEM = llList2String(REGION_LIST,NUMITEM); UPDATE(); } GET_FACTION(key id) { integer chan = (integer)("0x" + llGetSubString(id,0,6)); llRegionSay(chan,"GET_FACTION"); } GET_NAME(key id) { integer chan = (integer)("0x" + llGetSubString(id,0,6)); llRegionSay(chan,"GET_NAME"); } GET_NICKNAME(key id) { integer chan = (integer)("0x" + llGetSubString(id,0,6)); llRegionSay(chan,"GET_NICKNAME"); } GET_TITLE(key id) { integer chan = (integer)("0x" + llGetSubString(id,0,6)); llRegionSay(chan,"GET_TITLE"); } LAST_CATEGORY() { NUMCAT = llGetListLength(CATEGORIES) - 1; CURCAT = llList2String(CATEGORIES,NUMCAT); NUMITEM = 0; llRegionSay(REGION_DYN,"LIST_"+CURCAT); } LAST_ITEM() { NUMITEM = llGetListLength(REGION_LIST) - 1; CURITEM = llList2String(REGION_LIST,NUMITEM); UPDATE(); } NEXT_CATEGORY() { NUMCAT++; if ( NUMCAT >= llGetListLength(CATEGORIES) ) NUMCAT = 0; CURCAT = llList2String(CATEGORIES,NUMCAT); NUMITEM = 0; llRegionSay(REGION_DYN,"LIST_"+CURCAT); } NEXT_ITEM() { NUMITEM++; if ( NUMITEM >= llGetListLength(REGION_LIST) ) NUMITEM = 0; CURITEM = llList2String(REGION_LIST,NUMITEM); UPDATE(); } PREV_CATEGORY() { NUMCAT--; if ( NUMCAT < 0 ) NUMCAT = llGetListLength(CATEGORIES) - 1; CURCAT = llList2String(CATEGORIES,NUMCAT); NUMITEM = 0; llRegionSay(REGION_DYN,"LIST_"+CURCAT); } PREV_ITEM() { NUMITEM--; if ( NUMITEM < 0 ) NUMITEM = llGetListLength(REGION_LIST) - 1; CURITEM = llList2String(REGION_LIST,NUMITEM); UPDATE(); } RESET() { // do things llStopAnimation("turn_180"); llUnSit(llAvatarOnSitTarget()); } SAVE() { } SELL_ITEM() { } SET_FACTION() { if ( MENU_HAND == 0 ) { MENU_DYN = 1+(integer)llFrand(9999.0); MENU_HAND = llListen(MENU_DYN,"",NULL_KEY,""); llTextBox(llDetectedKey(0),"(Optional) What Is Your Character's Faction?\rYou have 60 seconds to enter a name.",MENU_DYN); llSetTimerEvent(60.0); } else { llSay(PUBLIC_CHANNEL,"Tool is already in use, please wait."); } } SET_NAME() { if ( MENU_HAND == 0 ) { MENU_DYN = 1+(integer)llFrand(9999.0); MENU_HAND = llListen(MENU_DYN,"",NULL_KEY,""); llTextBox(llDetectedKey(0),"What Is Your Character's First and Last Name?\rYou have 60 seconds to enter a name.",MENU_DYN); llSetTimerEvent(60.0); } else { llSay(PUBLIC_CHANNEL,"Tool is already in use, please wait."); } } SET_NICKNAME() { if ( MENU_HAND == 0 ) { MENU_DYN = 1+(integer)llFrand(9999.0); MENU_HAND = llListen(MENU_DYN,"",NULL_KEY,""); llTextBox(llDetectedKey(0),"(Optional) What Is Your Character's Nickname?\rYou have 60 seconds to enter a name.",MENU_DYN); llSetTimerEvent(60.0); } else { llSay(PUBLIC_CHANNEL,"Tool is already in use, please wait."); } } SET_TITLE() { if ( MENU_HAND == 0 ) { MENU_DYN = 1+(integer)llFrand(9999.0); MENU_HAND = llListen(MENU_DYN,"",NULL_KEY,""); llTextBox(llDetectedKey(0),"What Is Your Character's Title?\rExamples: Doctor, Reverend, etc.\rYou have 60 seconds to enter a name.",MENU_DYN); llSetTimerEvent(60.0); } else { llSay(PUBLIC_CHANNEL,"Tool is already in use, please wait."); } } SETUP() { // llSetText("Myriad Lite Character Editorder (Prototype)\nSit Here To Begin",<1,0,0>,1); vector OFFSET = <0,0,1.0>; llSitTarget(OFFSET,ZERO_ROTATION); llSetSitText("> EDIT <"); // put prim number/name pairs into list for UPDATE function to write text on prims integer i; string name; for (i = 0; i <= llGetNumberOfPrims(); i++) { name = llList2String(llGetLinkPrimitiveParams(i,[PRIM_NAME]),0); PRIMNAMES = PRIMNAMES + [name]; llSetLinkPrimitiveParamsFast(i,[PRIM_TEXT,"",<0,0,0>,0]); if ( llListFindList(CATEGORIES,[name]) != -1 ) { llSetLinkPrimitiveParamsFast(i,[PRIM_COLOR,ALL_SIDES,<1,0,0>,1]); } } // SETUP RENDEZVOUS1 MENU_DYN (STATIC) - backward compatible for Preview 6 and earlier //if ( MENU_HAND1 != 0 ) llListenRemove(MENU_HAND1); //MENU_HAND1 = llListen(RENDEZVOUS1,"",NULL_KEY,""); //llSay(PUBLIC_CHANNEL,"Rendezvous1 channel is "+(string)RENDEZVOUS1); // SETUP REGION_DYN MENU_DYN (DYNAMIC) - new for Preview 7 and later list details = llGetParcelDetails(<0,0,0>,[PARCEL_DETAILS_ID]); string parcelid = llList2String(details,0); REGION_DYN = (integer)("0x"+llGetSubString(parcelid,0,7)); if ( REGION_HAND != 0 ) llListenRemove(REGION_HAND); REGION_HAND = llListen(REGION_DYN,"",NULL_KEY,""); llSay(PUBLIC_CHANNEL,"Rendezvous2 channel is "+(string)REGION_DYN); // start listener last MY_DYN = (integer)("0x"+llGetSubString(llGetKey(),0,6)); if ( MY_HAND != 0 ) llListenRemove(MY_HAND); MY_HAND = llListen(MY_DYN,"",NULL_KEY,""); // CURCAT = llList2String(CATEGORIES,NUMCAT); // llRegionSay(REGION_DYN,"LIST_"+CURCAT); // request first category } // Utility function to target 1 prim SHOW_ON_PRIM(string primname,string data) { integer prim = llListFindList(PRIMNAMES,[primname]); if ( prim != -1 ) { llSetLinkPrimitiveParams(prim,[PRIM_TEXT,data,<1,1,1>,1.0]); } } UPDATE() { string out; integer prim; //prim = llListFindList(PRIMNAMES,["SHOW CATEGORY"]); //if ( prim != -1 && CURCAT != "" ) { // out = (string)(NUMCAT + 1) + " of " + llGetListLength(CATEGORIES) + ": " + CURCAT; // llSetLinkPrimitiveParams(prim,[PRIM_TEXT,out,<1,1,1>,1.0]); //} prim = llListFindList(PRIMNAMES,["SHOW ITEM"]); if ( prim != -1 && CURITEM != "" ) { out = CURCAT + (string)(NUMITEM + 1) + " of " + llGetListLength(REGION_LIST) + "\n" + CURITEM; llSetLinkPrimitiveParams(prim,[PRIM_TEXT,out,<1,1,1>,1.0]); } // update item cost // update character point pool left // update name // update faction // update species // update background // update career } default { changed(integer change) { if ( change & CHANGED_LINK ) { // someone sits or stands up WHO = llAvatarOnSitTarget(); if ( WHO == NULL_KEY ) RESET(); // stood up - reset if ( WHO != NULL_KEY ) { llRequestPermissions(WHO,PERMISSION_TRIGGER_ANIMATION); } } } listen(integer channel, string name, key id, string message) { if ( channel == MENU_DYN ) { integer chan = (integer)("0x"+llGetSubString((string)id,0,6)); if ( REQUEST == "NAMES" ) llRegionSay(chan,"SET_NAME|NAME="+message); if ( REQUEST == "NICKNAMES" ) llRegionSay(chan,"SET_NICKNAME|NICKNAME="+message); if ( REQUEST == "TITLES" ) llRegionSay(chan,"SET_TITLE|TITLE="+message); if ( REQUEST == "FACTIONS" ) llRegionSay(chan,"SET_FACTION|FACTION="+message); if ( MENU_HAND != 0 ) llListenRemove(MENU_HAND); llSetTimerEvent(0.0); MENU_HAND = 0; return; } // OBJECT DYNAMIC CHANNEL // Handle incoming LIST_ messages // Break down message into command and first attrib=data pair list tokens = llParseString2List(message,["|"],[]); string cmd = llList2String(tokens,0); // get the field before the first | string data = llList2String(tokens,1); list subtokens = llParseString2List(data,["="],[]); string attrib = llList2String(subtokens,0); string sdata = llList2String(subtokens,1); integer idata = llList2Integer(subtokens,1); if ( cmd == "CHARACTER" ) { if ( attrib == "NAME" ) { SHOW_ON_PRIM("TEXT1","Adventurer Name"); SHOW_ON_PRIM("TEXT2",sdata); return; } if ( attrib == "NICKNAME" ) { SHOW_ON_PRIM("TEXT1","Nickname"); SHOW_ON_PRIM("TEXT2",sdata); return; } if ( attrib == "TITLE" ) { SHOW_ON_PRIM("TEXT1","Title"); SHOW_ON_PRIM("TEXT2",sdata); return; } if ( attrib == "FACTION" ) { SHOW_ON_PRIM("TEXT1","Faction"); SHOW_ON_PRIM("TEXT2",sdata); return; } return; } if ( llListFindList(CATEGORIES,[cmd]) != -1 ) { // if that field is a category name, this is a reply to a LIST_ request REGION_LIST = llCSV2List( llList2String( llParseString2List(message,["|"],[]) ,1) ); // get the CSV list from response llSay(0,llList2CSV(REGION_LIST)); CURITEM = llList2String(REGION_LIST,NUMITEM); UPDATE(); return; } } run_time_permissions(integer perm) { if ( perm & PERMISSION_TRIGGER_ANIMATION ) { llStartAnimation("turn_180"); NUMCAT = 0; NUMITEM = 0; CURCAT = llList2String(CATEGORIES,NUMCAT); llRegionSay(REGION_DYN,"LIST_"+CURCAT); } } state_entry() { SETUP(); } timer() { if ( MENU_HAND != 0 ) llListenRemove(MENU_HAND); llSay(PUBLIC_CHANNEL,"Time expired. Please try again when ready."); MENU_HAND = 0; llSetTimerEvent(0.0); } touch_start(integer num_detected) { if ( WHO == NULL_KEY) return; // if no one on sit target, ignore clicks string action = llGetLinkName(llDetectedLinkNumber(0)); // get name of prim clicked in link set if ( action != "" && action != llGetObjectName() ) { // someone clicked a named button prim on this linkset COMMAND(action); // try that prim name as a command return; } } }