// 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