Allen Kerensky"It seems you've been living two lives ..."

Myriad Lite Module Meter

// Myriad_Lite_Module_Meter-v0.0.4-20131026.lsl
// Copyright (c) 2012 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 PPMA
// FIXME PPMA INCAP AND DEAD
// FIXME more RPEVENTS
// FIXME more HELP
// FIXME CHECK FOR REQUIRED RECORDS IN PPMA
 
string BASENAME = "Myriad Lite Module Meter";
string VERSION = "0.0.4"; // version number
string VERSIONDATE = "20131026"; // version date
 
// Module to Module Messaging Constants
integer MODULE_METER = -11;
integer LM_SENDTOATTACHMENT = 0x80000000;
integer RENDEZVOUS1 = -999;
 
// RUNTIME GLOBALS - CAN CHANGE DURING RUN
integer CHANATTACH; // dynamic channel for attachments
integer METERWORN; // using meter?
 
//
// PPMA GET_VAL
//
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 = 1;
        if ( setting == "MAXDAMAGE" ) retval = 5;
        ERROR("Unable to locate Myriad setting "+setting+" returning "+(string)retval);
    } else {
        retval = (integer)value;
    }
    return retval;
}
 
//
// PPMA GET_NAME - returns player firstname or nickname for Talker/Emoter
//
string GET_NAME() {
    string defaultname = "Myriad Player";
    string name = GET_VAL("CHARACTER","NAME");
    list tokens = llParseString2List(name,[" ",".","_"],[]);
    string firstname = llList2String(tokens,0);
    string lastname = llList2String(tokens,1);
    string nickname = GET_VAL("CHARACTER","NICKNAME");
    if ( name == KEY_NOT_FOUND && nickname == KEY_NOT_FOUND ) return defaultname;
    if ( name != KEY_NOT_FOUND && nickname == KEY_NOT_FOUND ) return name;
    if ( name == KEY_NOT_FOUND && nickname != KEY_NOT_FOUND ) return nickname;
    if ( name != KEY_NOT_FOUND && nickname != KEY_NOT_FOUND ) return firstname+" \""+nickname+"\" "+lastname;
    return defaultname;
}
 
// PPMA GET SPECIE
string GET_SPECIE() {
    string specie = GET_VAL("SPECIE","SPECIE");
    if ( specie == KEY_NOT_FOUND ) specie = "None";
    return specie;
}
 
// PPMA GET BACKGROUND
string GET_BACKGROUND() {
    string background = GET_VAL("BACKGROUND","BACKGROUND");
    if ( background == KEY_NOT_FOUND ) background = "None";
    return background;
}
 
// PPMA GET CAREER
string GET_CAREER() {
    string career = GET_VAL("CAREER","CAREER");
    if ( career == KEY_NOT_FOUND ) career = "None";
    return career;
}
 
// PPMA GET TITLE
string GET_TITLE() {
    string title = GET_VAL("CHARACTER","TITLE");
    if ( title == KEY_NOT_FOUND ) title = "";
    return title;
}
 
// PPMA GET FACTION
string GET_FACTION() {
    string faction = GET_VAL("CHARACTER","FACTION");
    if ( faction == KEY_NOT_FOUND ) faction = "";
    return faction;
}
 
//============================================================================
// DEBUG - show debug chat with wearer name for sorting
//============================================================================
DEBUG(string dmessage) {
    if ( GET_FLAG("DEBUG") == TRUE ) llMessageLinked(LINK_THIS,MODULE_METER,"DEBUG|"+dmessage,llGetOwner());
}
 
//============================================================================
// ERROR - show errors on debug channel with wearer name for sorting
//============================================================================
ERROR(string emessage) {
    llMessageLinked(LINK_THIS,MODULE_METER,"ERROR|"+emessage,llGetOwner());
}
 
//============================================================================
// GET_RESILIENCE
//============================================================================
integer GET_RESILIENCE(string name) {
    if ( name != "Wounds" && name != "CurrentWounds" && name != "CriticalWounds" && name != "CurrentCriticalWounds" && name != "Resolve" && name != "CurrentResolve") {
        ERROR("GET_RESILIENCE "+name+" invalid.");
        return -1;
    }
    string res = GET_VAL("RESILIENCE",name);
    if ( res == KEY_NOT_FOUND ) {
        ERROR("GET_RESILIENCE "+name+" not found in PPMA.");
        return -2;
    }
    integer val = (integer)res;
    if ( val < GET_MYRIAD("MINRESILIENCE") || val > GET_MYRIAD("MAXRESILIENCE") ) {
        ERROR("GET_RESILIENCE "+name+" invalid value "+res+" out of range "+(string)GET_MYRIAD("MINRESILIENCE")+"-"+(string)GET_MYRIAD("MAXRESILIENCE"));
        return -3;
    }
    return val;
}
 
// MEMORY
GET_MEMORY() {
    OWNERSAY(BASENAME+" free memory: "+(string)llGetFreeMemory()); // show this module's free memory info
}
 
// GETVERSION
GET_VERSION() {
    OWNERSAY(BASENAME+" v"+VERSION+"-"+VERSIONDATE); // show this module's version info
}
 
//============================================================================
// METER - update a hovertext health meter or HUD bar graph
//============================================================================
METER() {
    //if ( METERWORN == FALSE ) return;
    string name = GET_NAME();
    integer curwounds = GET_RESILIENCE("CurrentWounds");
    integer maxwounds = GET_RESILIENCE("Wounds");
    integer curcritical = GET_RESILIENCE("CurrentCriticalWounds");
    integer maxcritical = GET_RESILIENCE("CriticalWounds");
    integer flag_incapacitated = GET_FLAG("INCAPACITATED");
    integer flag_dead = GET_FLAG("DEAD");
    string  specie = GET_SPECIE();
    string  background = GET_BACKGROUND();
    string  career = GET_CAREER();
    integer resolve = GET_RESILIENCE("Resolve");
    integer curresolve = GET_RESILIENCE("CurrentResolve");
    string title = GET_TITLE();
    string faction = GET_FACTION();
    // create a meter message packet
    string ownername = llList2String(llParseString2List(llKey2Name(llGetOwner()),["@"],[]),0); // strip @where from HG names
    string message = "METER"+"|"+ownername+"|"+name+"|"+(string)curwounds+"|"+(string)maxwounds+"|"+(string)curcritical+"|"+(string)maxcritical+"|"+(string)flag_dead+"|"+(string)flag_incapacitated+"|"+specie+"|"+background+"|"+career+"|"+(string)curresolve+"|"+(string)resolve+"|"+title+"|"+faction;
    llRegionSay(RENDEZVOUS1,message); // send the update to region for scorekeepers, etc
    llWhisper(CHANATTACH,message); // whisper to the wearer's actual meter
    llMessageLinked(LINK_THIS,MODULE_METER,message,llGetOwner()); // send meter updates to bus
    DEBUG("Wounds: "+(string)curwounds+" of "+(string)maxwounds+" Critical: "+(string)curcritical+" of "+(string)maxcritical+" Resolve: "+(string)curresolve+" of "+(string)resolve);
}
 
//
// OWNERSAY - sent messages to player only
//
OWNERSAY(string message) {
    llMessageLinked(LINK_THIS,MODULE_METER,"OWNERSAY|"+message,llGetOwner());
}
 
//============================================================================
// RESET
//============================================================================
RESET() {
    llResetScript(); // now reset
}
 
//============================================================================
// SETUP - begin bringing the HUD online
//============================================================================
SETUP() {
 
    CHANATTACH = (integer)("0x"+llGetSubString((string)llGetOwner(),1,7)); // attachment-specific channel    
    OWNERSAY("Meter module active.");
}
 
//============================================================================
// DEFAULT STATE - load character sheet
//============================================================================
default {
 
    //
    // EVENT: CHANGED
    //
    changed(integer changes) {
        if ( changes & CHANGED_REGION || changes & CHANGED_TELEPORT ) {
            METER(); // update the meter after a shift
        }
    }
 
    // LINK MESSAGE - commands to and from other prims in HUD
    link_message(integer sender,integer sending_module,string str, key id) {
        if ( sending_module == MODULE_METER || sending_module == LM_SENDTOATTACHMENT ) return; // ignore our own link messages
 
        list fields = llParseString2List(str,["|"],[]); // break into list of fields based on "|"ider
        string command = llToLower(llStringTrim(llList2String(fields,0),STRING_TRIM)); // assume the first field is a Myriad Lite command
 
        if ( command == "debug" || command == "error" || command == "help" || command == "ownersay" || command == "rpevent" ) return; // ignore WELL commands
 
        // break down the rest of the message for this module
        //string data = llStringTrim(llList2String(fields,1),STRING_TRIM); // field one is the data
        //list subfields = llParseString2List(data,["="],[]); // break data field into comma-delimited subfields if needed
 
        // General Myriad Module Commnads
        if ( command == "memory" ) { GET_MEMORY(); return;} // get version when needed
        if ( command == "reset" ) { RESET(); return;} // reset when told
        if ( command == "version" ) { GET_VERSION(); return;} // get version when needed
 
        // only debug module specific message events
        DEBUG("EVENT: link_message("+(string)sender+","+(string)sending_module+","+str+","+(string)id+")");
 
        if ( command == "set_resilience" ) { // update meter when we see set resilience messages on the bus
            METER();
            return;
        }
        if ( command == "character_loaded" ) {
            METER();
            return; // we're out of notecard, so character sheet is loaded - start playing
        }
        if ( command == "attachmeter" ) {
            METERWORN = TRUE; // we need to send meter events
            METER(); // send update
            return;
        }
        if ( command == "detachmeter" ) { METERWORN = FALSE; return; }
        if ( command == "meter" ) { METER(); return; }
    }
 
    // STATE ENTRY
    state_entry() {
        // Check required character sheet data is in PPMA, if not, disable module until HUD reset
        // have to do this here, since state command cannot be called from global functions
        // See http://lslwiki.net/lslwiki/wakka.php?wakka=FunctionStateChangeHack
        // See also "Caveats" in http://wiki.secondlife.com/wiki/State
        list requirements = [ "RESILIENCE", "Wounds", "RESILIENCE", "CurrentWounds", "RESILIENCE", "CriticalWounds", "RESILIENCE", "CurrentCriticalWounds", "RESILIENCE", "Resolve", "RESILIENCE", "CurrentResolve", "MYRIAD", "MINRESILIENCE", "MYRIAD", "MAXRESILIENCE", "FLAG", "INCAPACITATED", "FLAG", "DEAD" ];
        integer i;
        for ( i = 0; i < llGetListLength(requirements); i += 2 ) {
            string category = llList2String(requirements, i);
            string aspect = llList2String(requirements, i + 1);
            if ( GET_VAL(category,aspect) == KEY_NOT_FOUND ) {
                OWNERSAY("Required "+llToLower(category)+" \""+aspect+"\" not found. Meter module will not work correctly. Disabling...");
                state disabled;
            }
        }
 
        SETUP();        
    }
} // end default state
 
state disabled {
    link_message(integer sender_num,integer sender,string message,key id) {
        if ( sender == MODULE_METER || sender == LM_SENDTOATTACHMENT ) return; // ignore our own messages
 
        list fields = llParseString2List(message,["|"],[]); // break line of text into = delimited fields
        string command = llToLower(llStringTrim(llList2String(fields,0),STRING_TRIM)); // field zero is the "command"
 
        if ( command == "debug" || command == "error" || command == "help" || command == "ownersay" || command == "rpevent" ) return; // ignore WELL commands
 
        if ( command == "reset" ) { RESET(); return; }    }
}
// END
This website uses cookies. By using the website, you agree with storing cookies on your computer. Also you acknowledge that you have read and understand our Privacy Policy. If you do not agree leave the website.More information about cookies
DokuWiki