// Myriad_Lite_Module_Generator-v0.0.0-20131117.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/ // FIXME - LEVEL TITLES - should this be part of the CAREER TEMPLATE? // FIXME CONVERT INCAP and DEAD to FLAG // FIXME more RPEVENT // FIXME more HELP // CONSTANTS - DO NOT CHANGE DURING RUN string BASENAME = "Myriad Lite Module Generator"; string VERSION = "0.0.0"; // Allen Kerensky's script version string VERSIONDATE = "20131117"; // Allen Kerensky's script yyyymmdd // Module to Module Messaging Constants integer MODULE_GENERATOR = -12; integer LM_SENDTOATTACHMENT = 0x80000000; // RUNTIME GLOBALS - MAY CHANGE // Prim Persistent Memory Array Support DELETE_RECORD(string dbkey, string field) { //OWNERSAY("DELETE_RECORD=["+dbkey+"] FIELD=["+field+"] START"); // scan index or prim names for empty, get number for update integer i; string name; string desc; for ( i = 2; i <= llGetNumberOfPrims(); i++) { name = llList2String(llGetLinkPrimitiveParams(i,[PRIM_NAME]),0); desc = llList2String(llGetLinkPrimitiveParams(i,[PRIM_DESC]),0); if ( name == dbkey && desc == field ) { // record found, delete llSetLinkPrimitiveParamsFast(i,[PRIM_NAME,"",PRIM_DESC,"",PRIM_TEXT,"",ZERO_VECTOR,0.0]); // save to database } } //OWNERSAY("DELETE_RECORD=["+dbkey+"] FIELD=["+field+"] ENDS"); } integer COUNT_TYPE(string type) { //OWNERSAY("COUNT_TYPE TYPE=["+type+"] STARTS"); type = llToUpper(type); // scan index or prim names for empty, get number for update integer count = 0; integer i; string name = ""; //string desc = ""; //string text = ""; for ( i = 2; i <= llGetNumberOfPrims(); i++) { name = llList2String(llGetLinkPrimitiveParams(i,[PRIM_NAME]),0); if ( name == type ) count++; } //OWNERSAY("COUNT_TYPE TYPE=["+type+"] COUNT=["+(string)count+"]"); return count; } DUMP_TYPE(integer chan,string type) { //OWNERSAY("DUMP_TYPES CHAN=["+(string)chan+"] TYPE=["+type+"] STARTS"); type = llToUpper(type); // scan index or prim names for empty, get number for update integer i; string name = ""; string desc = ""; string text = ""; for ( i = 2; i <= llGetNumberOfPrims(); i++) { name = llList2String(llGetLinkPrimitiveParams(i,[PRIM_NAME]),0); if ( name == type ) { desc = llList2String(llGetLinkPrimitiveParams(i,[PRIM_DESC]),0); text = llList2String(llGetLinkPrimitiveParams(i,[PRIM_TEXT]),0); if ( type == "PROGRESS" ) llSay(chan,"PROGRESS|"+desc+"="+text); if ( type == "STAT_INCREASE" ) llSay(chan,"STAT_INCREASE|"+desc+"="+text); if ( type == "SKILL_INCREASE" ) llSay(chan,"SKILL_INCREASE|"+desc+"="+text); } } //OWNERSAY("DUMP_TYPE ENDS"); } // FIXME NEEDS TO BECOME LINK MESSAGE TO MOD_CHARSHEET! ERASE_TYPE(string type) { //OWNERSAY("ERASE TYPE ["+type+"] STARTS"); // scan index or prim names for empty, get number for update integer i; string name = ""; string desc = ""; for ( i = 2; i <= llGetNumberOfPrims(); i++) { name = llList2String(llGetLinkPrimitiveParams(i,[PRIM_NAME]),0); if ( name == type ) { desc = llList2String(llGetLinkPrimitiveParams(i,[PRIM_DESC]),0); DELETE_RECORD(type,desc); } } //OWNERSAY("ERASE_TYPE ENDS"); } string KEY_NOT_FOUND = "[KEY_NOT_FOUND]"; string GET_VAL(string dbkey,string field) { //OWNERSAY("GET_VAL KEY=["+dbkey+"] FIELD=["+field+"]"); string out = KEY_NOT_FOUND; integer i; string name; string desc; for ( i = 2; i <= llGetNumberOfPrims(); i++ ) { name = llList2String(llGetLinkPrimitiveParams(i,[PRIM_NAME]),0); desc = llList2String(llGetLinkPrimitiveParams(i,[PRIM_DESC]),0); if ( llToLower(name) == llToLower(dbkey) && llToLower(desc) == llToLower(field) ) { out = llList2String(llGetLinkPrimitiveParams(i,[PRIM_TEXT]),0); //DEBUG("GET_VAL RETURN=["+out+"]"); return out; // bail on first match? } } //OWNERSAY("GET_VAL RETURN=["+out+"]"); return out; } SET_VAL(string dbkey, string field, string val) { //OWNERSAY("SET_VAL KEY=["+dbkey+"] FIELD=["+field+"] VAL=["+val+"]"); integer i; string name; string desc; integer written = FALSE; for ( i = 2; i <= llGetNumberOfPrims(); i++ ) { name = llStringTrim(llList2String(llGetLinkPrimitiveParams(i,[PRIM_NAME]),0),STRING_TRIM); desc = llStringTrim(llList2String(llGetLinkPrimitiveParams(i,[PRIM_DESC]),0),STRING_TRIM); if ( ( llToLower(name) == llToLower(dbkey) && llToLower(desc) == llToLower(field) ) && written == FALSE ) { //OWNERSAY("SET_VAL UPDATE RECORD=["+(string)i+"] DBKEY=["+dbkey+"] DESC=["+field+"] VAL=["+val+"]"); llSetLinkPrimitiveParamsFast(i,[PRIM_NAME,dbkey,PRIM_DESC,field,PRIM_TEXT,val,ZERO_VECTOR,0.0]); written = TRUE; // we did an update, remember it } } if ( written == TRUE ) { //OWNERSAY("SET_VAL UPDATE COMPLETE."); return; } // data hasn't been written, scan for free prim for ( i = 2; i <= llGetNumberOfPrims(); i++ ) { name = llStringTrim(llList2String(llGetLinkPrimitiveParams(i,[PRIM_NAME]),0),STRING_TRIM); desc = llStringTrim(llList2String(llGetLinkPrimitiveParams(i,[PRIM_DESC]),0),STRING_TRIM); if ( ( name == "" && desc == "" ) && written == FALSE ) { //OWNERSAY("SET_VAL INSERT RECORD=["+(string)i+"] DBKEY=["+dbkey+"] DESC=["+field+"] VAL=["+val+"]"); llSetLinkPrimitiveParamsFast(i,[PRIM_NAME,dbkey,PRIM_DESC,field,PRIM_TEXT,val,ZERO_VECTOR,0.0]); written = TRUE; // we did an update, remember it } } if ( written == TRUE ) { //OWNERSAY("SET_VAL INSERT COMPLETED."); return; } //OWNERSAY("SET_VAL NO FREE RECORD FOUND TO INSERT INTO! DATA LOST"); } ////////////////////////////////////////////////////////////////////////////// // FLAG FUNCTIONS // INCAPACITATED - lost wounds // DEAD - lost critical wounds // DEBUG - show debug messages or not // IDEA: INDECISION - lost resolve? // LMIM: SET_FLAG|<name>=<TRUE|FALSE> // PPMA: FLAG,<flagname>,<TRUE|FALSE> // LMOUT: FLAG|<flagname>=<TRUE|FALSE> // LMERR: FIXME integer GET_FLAG(string flag) { string val = GET_VAL("FLAG",llToUpper(flag)); if ( val == KEY_NOT_FOUND ) { ERROR("Flag ["+flag+"] does not exist."); } if ( val != "0" && val != "1") { ERROR("Flag: "+flag+" invalid value ["+val+"]"); } integer bool = (integer)val; return bool; } // SET_FLAG // LMIM: SET_FLAG|<flagname>=<TRUE|FALSE> // PPMA: FLAG,<flagname>,<TRUE|FALSE> // LMOUT: SET_FLAG|<flagname>=<TRUE|FALSE> // LMERR: FIXME SET_FLAG(string flag,integer value) { if ( flag == "" ) return; // FIXME add error if ( value != TRUE && value != FALSE ) return; // FIXME add err SET_VAL("FLAG",llToUpper(flag),(string)value); } // // GET_MYRIAD // Requires a MYRIAD CONSTANT NAME // Returns the amount of that Myriad rules constant or defaultif the player does not currently have that constant // integer GET_MYRIAD(string setting) { integer retval; string value = GET_VAL("MYRIAD",setting); if ( value == KEY_NOT_FOUND ) { if ( setting == "MINSTAT" ) retval = 1; if ( setting == "MAXSTAT" ) retval = 10; if ( setting == "MINSKILL" ) retval = 0; if ( setting == "MAXSKILL" ) retval = 7; if ( setting == "MINEFFECT" ) retval = 0; if ( setting == "MAXEFFECT" ) retval = 5; if ( setting == "MINRESILIENCE" ) retval = 0; if ( setting == "MAXRESILIENCE" ) retval = 20; if ( setting == "MINBOON" ) retval = 0; if ( setting == "MAXBOON" ) retval = 5; if ( setting == "MINFLAW" ) retval = 0; if ( setting == "MAXFLAW" ) retval = 5; if ( setting == "MINRP" ) retval = 0; if ( setting == "MAXRP" ) retval = 10; if ( setting == "MINITEM" ) retval = 0; if ( setting == "MAXITEM" ) retval = 100; if ( setting == "MINARMOR" ) retval = 0; if ( setting == "MAXARMOR" ) retval = 5; if ( setting == "MINDAMAGE" ) retval = 0; if ( setting == "MAXDAMAGE" ) retval = 5; SET_VAL("MYRIAD",setting,(string)retval); ERROR("Unable to locate Myriad setting "+setting+" returning "+(string)retval); } else { retval = (integer)value; } return retval; } // STATISTICS integer GET_STATISTIC(string stat) { // FIXME how to verify stat? integer points = (integer)GET_VAL("STATISTIC",stat); integer minstat = GET_MYRIAD("MINSTAT"); integer maxstat = GET_MYRIAD("MAXSTAT"); if ( points < minstat ) { points = minstat; SET_STATISTIC(stat,points); } if ( points > maxstat ) { points = maxstat; SET_STATISTIC(stat,points); } return points; } SET_STATISTIC(string statname,integer statrank) { // FIXME how to verify stat names are valid? integer minstat = GET_MYRIAD("MINSTAT"); integer maxstat = GET_MYRIAD("MAXSTAT"); if ( statrank < minstat ) statrank = minstat; if ( statrank > maxstat ) statrank = maxstat; llMessageLinked(LINK_THIS,MODULE_GENERATOR,"SET_STATISTIC|"+statname+"="+(string)statrank,llGetOwner()); // Notify CharSheet to update statistic } // SKILLS integer GET_SKILL(string skill) { integer rank = (integer)GET_VAL("SKILL",skill); integer minskill = GET_MYRIAD("MINSKILL"); integer maxskill = GET_MYRIAD("MAXSKILL"); if ( rank < minskill ) { rank = minskill; SET_SKILL(skill,rank); } if ( rank > maxskill ) { rank = maxskill; SET_SKILL(skill,rank); } return rank; } SET_SKILL(string skill,integer rank) { // FIXME how to verify skill names are valid? integer minskill = GET_MYRIAD("MINSKILL"); integer maxskill = GET_MYRIAD("MAXSKILL"); if ( rank < minskill ) rank = minskill; if ( rank > maxskill ) rank = maxskill; llMessageLinked(LINK_THIS,MODULE_GENERATOR,"SET_SKILL|"+skill+"="+(string)rank,llGetOwner()); // notify character sheet to update skill } // SFX integer GET_EFFECT(string name) { integer rank = (integer)GET_VAL("EFFECT",name); integer mineffect = GET_MYRIAD("MINEFFECT"); integer maxeffect = GET_MYRIAD("MAXEFFECT"); if ( rank < mineffect ) { rank = mineffect; SET_EFFECT(name,rank); } if ( rank > maxeffect ) { rank = maxeffect; SET_EFFECT(name,rank); } return rank; } SET_EFFECT(string name,integer rank) { // FIXME how to verify effect name? integer mineffect = GET_MYRIAD("MINEFFECT"); integer maxeffect = GET_MYRIAD("MAXEFFECT"); if ( rank < mineffect ) rank = mineffect; if ( rank > maxeffect ) rank = maxeffect; llMessageLinked(LINK_THIS,MODULE_GENERATOR,"SET_EFFECT|"+name+"="+(string)rank,llGetOwner()); // notify character sheet to update effect } // RESILIENCES integer GET_RESILIENCE(string name) { integer cr = (integer)GET_VAL("RESILIENCE",name); integer minres = GET_MYRIAD("MINRESILIENCE"); integer maxres = GET_MYRIAD("MAXRESILIENCE"); if ( cr < minres ) { cr = minres; SET_RESILIENCE(name,cr); } if ( cr > maxres ) { cr = maxres; SET_RESILIENCE(name,cr); } return cr; } SET_RESILIENCE(string resname,integer resrank) { // FIXME how to verify resilience names are valid? integer minres = GET_MYRIAD("MINRESILIENCE"); integer maxres = GET_MYRIAD("MAXRESILIENCE"); if ( resrank < minres ) resrank = minres; if ( resrank > maxres ) resrank = maxres; llMessageLinked(LINK_THIS,MODULE_GENERATOR,"SET_RESILIENCE|"+resname+"="+(string)resrank,llGetOwner()); //notify character sheet to update resilience } ///////////// // UTILITY // ///////////// // // DEBUG - show debug chat with wearer name for sorting // DEBUG(string dmessage) { if ( GET_FLAG("DEBUG") == TRUE ) llMessageLinked(LINK_THIS,MODULE_GENERATOR,"DEBUG|"+dmessage,llGetOwner()); } // // ERROR - show errors on debug channel with wearer name for sorting // ERROR(string emessage) { llMessageLinked(LINK_THIS,MODULE_GENERATOR,"ERROR|"+emessage,llGetOwner()); } // // GET_MEMORY // GET_MEMORY() { OWNERSAY(BASENAME+" free memory: "+(string)llGetFreeMemory()); // show this module's free memory info } // // GET_VERSION // GET_VERSION() { OWNERSAY(BASENAME+" v"+VERSION+"-"+VERSIONDATE); // show this module's version info } // // OWNERSAY // OWNERSAY(string msg) { llMessageLinked(LINK_THIS,MODULE_GENERATOR,"OWNERSAY|"+msg,llGetOwner()); } // // PARSE // PARSE(string message,key id) { // No need for debug - only link messages to this module and debug is done there // First - handle type 1 messages that do not require breaking down list tokens = llParseString2List(message,["|"],[]); string cmd = llToLower(llStringTrim(llList2String(tokens,0),STRING_TRIM)); string data = llList2String(tokens,1); list subtokens = llParseString2List(data,["="],[]); string attrib = llList2String(subtokens,0); integer idata = llList2Integer(subtokens,1); string sdata = llList2String(subtokens,1); if ( cmd == "memory" ) { GET_MEMORY(); return; } if ( cmd == "reset" ) { RESET(); return; } if ( cmd == "version" ) { GET_VERSION(); return;} // show version info } // // RESET - shut down running animations then reset the script to reload character sheet // RESET() { llResetScript(); // now reset } // // RPEVENT // RPEVENT(string rpevent) { llMessageLinked(LINK_THIS,MODULE_GENERATOR,"RPEVENT|"+rpevent,llGetOwner()); } // // SETUP - begin bringing the HUD online // SETUP() { OWNERSAY("Generator module active."); } // // DEFAULT STATE // default { link_message(integer sender_num,integer sender,string message,key id) { if ( sender == MODULE_GENERATOR || sender == LM_SENDTOATTACHMENT ) return; // ignore link messages not sent to us specifically // First - handle type 1 messages that do not require breaking down list tokens = llParseString2List(message,["|"],[]); string cmd = llToLower(llStringTrim(llList2String(tokens,0),STRING_TRIM)); if ( cmd == "debug" || cmd == "error" || cmd == "help" || cmd == "ownersay" || cmd == "rpevent" ) return; // ignore WELL commands // only debug when its module specific DEBUG("EVENT: link_message("+(string)sender_num+","+(string)sender+","+message+","+(string)id+")"); PARSE(message,id); // parse incoming message } // end of link_message event // STATE ENTRY - called on Reset state_entry() { SETUP(); // show credits and start character sheet load } } // end state // END