// Myriad_Lite_Module_Progress-v0.0.2-20131019.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 Progress"; string VERSION = "0.0.2"; // Allen Kerensky's script version string VERSIONDATE = "20131019"; // Allen Kerensky's script yyyymmdd // Module to Module Messaging Constants integer MODULE_PROGRESS = -9; integer LM_SENDTOATTACHMENT = 0x80000000; // RUNTIME GLOBALS - MAY CHANGE //integer XP; //integer XPLEVEL; list XP_BY_LEVEL; // list of XP per level from 0 to 30 integer ADD_XP_SESSION; // total of XP player has earned this session string PROGRESSION; // Progression Method: LEVEL, GRADUAL, or RANDOM integer FLAG_SESSION; // TRUE if player in session, FALSE if player out of session integer XPSPENT; integer DEL_XP_SESSION; // total of XP player lost this session // 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; // CAMPAIGN constants FIXME Get from region server if ( setting == "MINGP" ) retval = 0; if ( setting == "MAXGP" ) retval = 112; // GP for godlike campaign if ( setting == "MINSTATPOOL" ) retval = 0; if ( setting == "MAXSTATPOOL" ) retval = 48; // 12 example stats in book times 4 pts per stat in godlike campaign if ( setting == "MINHEALTHPOOL") retval = 0; if ( setting == "MAXHEALTHPOOL") retval = 48; // 6 example resilience times 8 pts per resilience in godlike campaign if ( setting == "MINSKILLPOOL") retval = 0; if ( setting == "MAXSKILLPOOL") retval = 36; // 4 per 4 skills in godlike campaign, 36 example skills in book if ( setting == "MINEFFECTPOOL") retval = 0; if ( setting == "MAXEFFECTPOOL") retval = 7; // for godlike campaigns // Progress XP if ( setting == "MINXPLEVEL" ) retval = 1; if ( setting == "MAXXPLEVEL" ) retval = 30; if ( setting == "MINXP" ) retval = 0; if ( setting == "MAXXP") retval = 2320; if ( setting == "MINADDXP" ) retval = 1; if ( setting == "MAXADDXP" ) retval = 10; if ( setting == "MINDELXP" ) retval = 1; if ( setting == "MAXDELXP" ) retval = 10; if ( setting == "XPSCALE" ) retval = 1; // XPSCALE can be 1 or 10, FIXME region setting // XP_BY_LEVEL = [ 0,0,10,25,45,70,100,135,175,220,270,325,385,450,520,595,675,760,850,945,1045,1150,1260,1375,1495,1620,1750,1885,2025,2170,2320 ]; // Progress Gradual if ( setting == "STATCOSTFACTOR" ) retval = 5; if ( setting == "SKILLCOSTFACTOR" ) retval = 3; if ( setting == "EFFECTCOSTBASE" ) retval = 5; if ( setting == "EFFECTCOSTFACTOR" ) retval = 2; // Progress Random if ( setting == "MINSTATINC" ) retval = 0; if ( setting == "MAXSTATINC" ) retval = 5; // after 5 stat increases, it should reset if ( setting == "MINSKILLINC" ) retval = 0; if ( setting == "MAXSKILLINC" ) retval = 5; if ( setting == "MINNEWSKILLS" ) retval = 0; if ( setting == "MAXNEWSKILLS" ) retval = 7; // FIXME arbitrarily chosen amount 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_PROGRESS,"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_PROGRESS,"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_PROGRESS,"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_PROGRESS,"SET_RESILIENCE|"+resname+"="+(string)resrank,llGetOwner()); //notify character sheet to update resilience } ////////////////////// // PROGRESS UTILITY // ////////////////////// DEL_PROGRESS(key id) { key objectowner = llList2Key(llGetObjectDetails(id,[OBJECT_OWNER]),0); key regionowner = llList2Key(llGetParcelDetails(<0,0,0>,[PARCEL_DETAILS_OWNER]),0); if ( objectowner != regionowner ) { ERROR("DEL_PROGRESS called by object or player who is not region owner. ["+(string)objectowner+"]["+(string)regionowner+"]"); return; } // Delete all progress for LEVEL, GRADUAL, and RANDOM SET_STATPOOL(0); SET_HEALTHPOOL(0); SET_SKILLPOOL(0); SET_EFFECTPOOL(0); SET_XPLEFT(0); SET_SKILL_INC(0); SET_NEW_SKILLS(0); ERASE_TYPE("SKILL_INCREASE"); ERASE_TYPE("STAT_INCREASE"); SET_SIXES_BURNED(0); } DUMP_PROGRESS(key id) { // id to dump progress back to key objectowner = llList2Key(llGetObjectDetails(id,[OBJECT_OWNER]),0); key regionowner = llList2Key(llGetParcelDetails(<0,0,0>,[PARCEL_DETAILS_OWNER]),0); if ( objectowner != regionowner ) { ERROR("DUMP_PROGRESS called by object or player who is not region owner. ["+(string)objectowner+"]["+(string)regionowner+"]"); return; } integer chan = (integer)("0x"+llGetSubString((key)id,0,6)); DUMP_TYPE(chan,"PROGRESS"); DUMP_TYPE(chan,"STAT_INCREASE"); DUMP_TYPE(chan,"SKILL_INCREASE"); llSay(chan,"PROGRESS_LOADED"); } END_SESSION() { if ( FLAG_SESSION == TRUE ) { DEBUG("Session ending. "+(string)ADD_XP_SESSION+"XP earned."); FLAG_SESSION = FALSE; } } REPORT_POOLS() { string report = "PROGRESS"; if ( PROGRESSION == "LEVEL" ) { report += "|"+"XP="+(string)GET_XP(); report += "|"+"XPLEVEL="+(string)GET_XPLEVEL(); report += "|"+"STATPOOL="+(string)GET_STATPOOL(); report += "|"+"SKILLPOOL="+(string)GET_SKILLPOOL(); report += "|"+"HEALTHPOOL="+(string)GET_HEALTHPOOL(); report += "|"+"SFXPOOL="+(string)GET_EFFECTPOOL(); } if ( PROGRESSION == "GRADUAL" ) { report += "|"+"XP="+(string)GET_XP(); report += "|"+"XPSPENT="+(string)XPSPENT; } if ( PROGRESSION == "RANDOM" ) { DEBUG("RANDOM"); // FIXME PPMA Storage of CSV list PROGRESS,STATISTICSUSED,<csv_statname_times> // FIXME PPMA Storage of CSV list PROGRESS,SKILLSUSED,<csv_skillname_times> // FIXME PPMA Storage of CSV list PROGRESS,EFFECTSUSED,<csv_effectname_times> } llMessageLinked(LINK_THIS,MODULE_PROGRESS,report,llGetOwner()); } SET_PROGRESSION(string method) { if ( method == "LEVEL" || method == "GRADUAL" || method == "RANDOM" ) { PROGRESSION = method; DEBUG("Character progression method set to: "+method); } else { ERROR("Unknown progression method: "+method+"! Roleplay progress will not be counted."); } } START_SESSION() { if ( PROGRESSION != "LEVEL" || PROGRESSION != "GRADUAL" || PROGRESSION != "RANDOM" ) { ERROR("Progression method not set. Cannot start roleplay session. Roleplay progress will not be counted."); return; } if ( FLAG_SESSION == FALSE ) { DEBUG("Session starting."); FLAG_SESSION = TRUE; ADD_XP_SESSION = 0; // zero out the XP earned this session counter } } //////////////// // GENERATORS // //////////////// // // GET_GP // integer GET_GP() { integer gp = (integer)GET_VAL("PROGRESS","GP"); integer mingp = GET_MYRIAD("MINGP"); integer maxgp = GET_MYRIAD("MAXGP"); if ( gp < mingp ) { gp = mingp; SET_GP(gp); } if ( gp > maxgp ) { gp = maxgp; SET_GP(gp); } llMessageLinked(LINK_THIS,MODULE_PROGRESS,"PROGRESS|GP="+(string)gp,llGetOwner()); // FIXME remove unneeded link message when PPMA complete return gp; } SET_GP(integer gpamt) { integer mingp = GET_MYRIAD("MINGP"); integer maxgp = GET_MYRIAD("MAXGP"); if ( gpamt < mingp ) gpamt = mingp; if ( gpamt > maxgp ) gpamt = maxgp; SET_VAL("PROGRESS","GP",(string)gpamt); llMessageLinked(LINK_THIS,MODULE_PROGRESS,"PROGRESS|GP="+(string)gpamt,llGetOwner()); // FIXME remove unneeded link message when PPMA complete } // STATPOOL - GENERATOR POINTBUY, UPDATER LEVEL integer GET_STATPOOL() { integer sp = (integer)GET_VAL("PROGRESS","STATPOOL"); integer minstatpool = GET_MYRIAD("MINSTATPOOL"); integer maxstatpool = GET_MYRIAD("MAXSTATPOOL"); if ( sp < minstatpool ) { sp = minstatpool; SET_STATPOOL(sp); } if ( sp > maxstatpool ) { sp = maxstatpool; SET_STATPOOL(sp); } llMessageLinked(LINK_THIS,MODULE_PROGRESS,"PROGRESS|STATPOOL="+(string)sp,llGetOwner()); // FIXME remove unneeded link message when PPMA complete return sp; } SET_STATPOOL(integer statamt) { integer minstatpool = GET_MYRIAD("MINSTATPOOL"); integer maxstatpool = GET_MYRIAD("MAXSTATPOOL"); if ( statamt < minstatpool ) statamt = minstatpool; if ( statamt > maxstatpool ) statamt = maxstatpool; SET_VAL("PROGRESS","STATPOOL",(string)statamt); llMessageLinked(LINK_THIS,MODULE_PROGRESS,"PROGRESS|STATPOOL="+(string)statamt,llGetOwner()); //FIXME remove unneeded link message when PPMA complete } // HEALTHPOOL - GENERATOR POINTBUY, UPDATER LEVEL integer GET_HEALTHPOOL() { integer hp = (integer)GET_VAL("PROGRESS","HEALTHPOOL"); integer minhealthpool = GET_MYRIAD("MINHEALTHPOOL"); integer maxhealthpool = GET_MYRIAD("MAXHEALTHPOOL"); if ( hp < minhealthpool ) { hp = minhealthpool; SET_HEALTHPOOL(hp); } if ( hp > maxhealthpool ) { hp = maxhealthpool; SET_HEALTHPOOL(hp); } llMessageLinked(LINK_THIS,MODULE_PROGRESS,"PROGRESS|HEALTHPOOL="+(string)hp,llGetOwner()); // FIXME remove unneeded link message when PPMA complete return hp; } SET_HEALTHPOOL(integer healthamt) { integer minhealthpool = GET_MYRIAD("MINHEALTHPOOL"); integer maxhealthpool = GET_MYRIAD("MAXHEALTHPOOL"); if ( healthamt < minhealthpool ) healthamt = minhealthpool; if ( healthamt > maxhealthpool ) healthamt = maxhealthpool; SET_VAL("PROGRESS","HEALTHPOOL",(string)healthamt); llMessageLinked(LINK_THIS,MODULE_PROGRESS,"PROGRESS|HEALTHPOOL="+(string)healthamt,llGetOwner()); // FIXME remove unneeded link message when PPMA complete } // SKILLPOOL - GENERATOR POINTBUY, UPDATER LEVEL integer GET_SKILLPOOL() { integer skp = (integer)GET_VAL("PROGRESS","SKILLPOOL"); integer minskillpool = GET_MYRIAD("MINSKILLPOOL"); integer maxskillpool = GET_MYRIAD("MAXSKILLPOOL"); if ( skp < minskillpool ) { skp = minskillpool; SET_SKILLPOOL(skp); } if ( skp > maxskillpool ) { skp = maxskillpool; SET_SKILLPOOL(skp); } llMessageLinked(LINK_THIS,MODULE_PROGRESS,"PROGRESS|SKILLPOOL="+(string)skp,llGetOwner()); // FIXME remove unneeded link message when PPMA complete return skp; } SET_SKILLPOOL(integer skillamt) { integer minskillpool = GET_MYRIAD("MINSKILLPOOL"); integer maxskillpool = GET_MYRIAD("MAXSKILLPOOL"); if ( skillamt < minskillpool ) skillamt = minskillpool; if ( skillamt > maxskillpool ) skillamt = maxskillpool; SET_VAL("PROGRESS","SKILLPOOL",(string)skillamt); llMessageLinked(LINK_THIS,MODULE_PROGRESS,"PROGRESS|SKILLPOOL="+(string)skillamt,llGetOwner()); //FIXME remove unneeded link message when PPMA complete } // SFXPOOL - GENERATOR POINTBUY, UPDATER LEVEL integer GET_EFFECTPOOL() { integer sfp = (integer)GET_VAL("PROGRESS","EFFECTPOOL"); integer mineffectpool = GET_MYRIAD("MINEFFECTPOOL"); integer maxeffectpool = GET_MYRIAD("MAXEFFECTPOOL"); if ( sfp < mineffectpool ) { sfp = mineffectpool; SET_EFFECTPOOL(sfp); } if ( sfp > maxeffectpool ) { sfp = maxeffectpool; SET_EFFECTPOOL(sfp); } llMessageLinked(LINK_THIS,MODULE_PROGRESS,"PROGRESS|SFXPOOL="+(string)sfp,llGetOwner()); // FIXME remove unneeded link message when PPMA complete return sfp; } SET_EFFECTPOOL(integer sfxamt) { integer mineffectpool = GET_MYRIAD("MINEFFECTPOOL"); integer maxeffectpool = GET_MYRIAD("MAXEFFECTPOOL"); if ( sfxamt < mineffectpool ) sfxamt = mineffectpool; if ( sfxamt > maxeffectpool ) sfxamt = maxeffectpool; SET_VAL("PROGRESS","EFFECTPOOL",(string)sfxamt); llMessageLinked(LINK_THIS,MODULE_PROGRESS,"PROGRESS|SFXPOOL="+(string)sfxamt,llGetOwner()); // FIXME remove unneeded link message when PPMA complete } /////////////////////////// // PROGRESS: LEVEL-BASED // /////////////////////////// // // XP integer GET_XP() { integer xp = (integer)GET_VAL("PROGRESS","XP"); integer minxp = GET_MYRIAD("MINXP"); integer maxxp = GET_MYRIAD("MAXXP"); if ( xp < minxp ) { xp = minxp; SET_XP(xp); } if ( xp > maxxp ) { xp = maxxp; SET_XP(xp); } llMessageLinked(LINK_THIS,MODULE_PROGRESS,"PROGRESS|XP="+(string)xp,llGetOwner()); return xp; } SET_XP(integer amount) { integer xp; integer minxp = GET_MYRIAD("MINXP"); integer maxxp = GET_MYRIAD("MAXXP"); integer xplevel = GET_XPLEVEL(); if ( amount >= minxp && amount <= maxxp ) { xp = amount; integer templevel = GET_LEVEL_BY_XP(xp); if ( templevel != 0 ) { if ( templevel > xplevel ) { // player is levelling up! LEVELUP(templevel); // level up player } xplevel = templevel; // set new XP level to current } DEBUG("XP set to: "+(string)xp+" XPLEVEL set to: "+(string)xplevel); } else { ERROR("XP "+(string)amount+" out of range: "+(string)minxp+"-"+(string)maxxp); } if ( xp < minxp ) xp = minxp; if ( xp > maxxp ) xp = maxxp; SET_VAL("PROGRESS","XP",(string)xp); llMessageLinked(LINK_THIS,MODULE_PROGRESS,"PROGRESS|XP="+(string)xp,llGetOwner()); } ADD_XP(integer amount) { integer maxxp = GET_MYRIAD("MAXXP"); integer minaddxp = GET_MYRIAD("MINADDXP"); integer maxaddxp = GET_MYRIAD("MAXADDXP"); if ( amount >= minaddxp && amount <= maxaddxp ) { if ( amount + ADD_XP_SESSION > maxaddxp ) { DEBUG("Max XP gain per session reached. Unable to add more XP."); } else { SET_XP(GET_XP() + amount); // add XP to player pool ADD_XP_SESSION += amount; // keep track of how many earned this session } } else { ERROR("ADD_XP amount "+(string)amount+" out of range: "+(string)minaddxp+"-"+(string)maxaddxp); } if ( GET_XP() > maxxp ) SET_XP(maxxp); // FIXME need to set XP in PPMA lol } // ADD_XP - Add a point of XP ADD_XP2(key granterid) { key objectowner = llList2Key(llGetObjectDetails(granterid,[OBJECT_OWNER]),0); key regionowner = llList2Key(llGetParcelDetails(<0,0,0>,[PARCEL_DETAILS_OWNER]),0); if ( objectowner != regionowner ) { ERROR("ADD_XP called by object or player who is not region owner. ["+(string)objectowner+"]["+(string)regionowner+"]"); return; } DEBUG("Progression="+PROGRESSION+" XP="+(string)GET_XP()+" XPLEVEL="+(string)GET_XPLEVEL()); if ( PROGRESSION == "RANDOM" ) { ERROR("Unable to add XP in region using Random Progression"); return; } integer maxxp = GET_MYRIAD("MAXXP"); if ( GET_XP() < maxxp ) { SET_XP( GET_XP() + 1); // add one to total XP if ( PROGRESSION == "LEVEL-BASED" ) { integer currentlevel = GET_XPLEVEL(); integer templevel = GET_LEVEL_BY_XP(GET_XP()); if ( templevel > currentlevel ) { SET_XPLEVEL(templevel); string ownername = llList2String(llParseString2List(llKey2Name(llGetOwner()),["@"],[]),0); // strip @where from HG names OWNERSAY("LEVEL UP! Congratulations, you are now XP Level "+(string)GET_XPLEVEL()); RPEVENT("LEVEL UP! Congratulations, "+ownername+" is now XP Level "+(string)GET_XPLEVEL()); LEVELUP(GET_XPLEVEL()); } return; } if ( PROGRESSION == "GRADUAL" ) { SET_XPLEFT ( GET_XPLEFT() + 1); // add one to XP you can spend in gradual progress mode return; } llMessageLinked(LINK_THIS,MODULE_PROGRESS,"XP_CHANGED|XP="+(string)GET_XP(),llGetOwner()); DEBUG("Progression="+PROGRESSION+" XP="+(string)GET_XP()+" XPLEVEL="+(string)GET_XPLEVEL()); } else { ERROR("ADD_XP(): XP already maxed."); } } DEL_XP(integer amount) { integer minxp = GET_MYRIAD("MINXP"); integer mindelxp = GET_MYRIAD("MINDELXP"); integer maxdelxp = GET_MYRIAD("MAXDELXP"); if ( amount >= mindelxp && amount <= maxdelxp ) { if ( amount + DEL_XP_SESSION > maxdelxp ) { DEBUG("Max XP loss per session reached. Unable to add more XP."); } else { SET_XP(GET_XP() - amount); // add XP to player pool DEL_XP_SESSION += amount; // } } else { ERROR("DEL_XP amount "+(string)amount+" out of range: "+(string)mindelxp+"-"+(string)maxdelxp); } if ( GET_XP() < 0 ) SET_XP(minxp); // FIXME save XP to PPMA lol } integer GET_LEVEL_BY_XP(integer amount) { integer count = 0; integer outlevel = 0; integer maxxplevel = GET_MYRIAD("MAXXPLEVEL"); for (count = 0; count < maxxplevel; count++ ) { if ( amount > llList2Integer(XP_BY_LEVEL,count) ) outlevel = count; } DEBUG("GET_LEVEL_BY_XP("+(string)amount+") returning "+(string)outlevel); return outlevel; } ADD_XPLEVEL() { integer maxxplevel = GET_MYRIAD("MAXXPLEVEL"); integer xplevel = GET_XPLEVEL(); if ( xplevel < maxxplevel ) { SET_XPLEVEL(xplevel++); // add one DEBUG("Level added. New level: "+(string)xplevel); } else { ERROR("Unable to add a level. Current level already: "+(string)xplevel); } integer tempxp = GET_XP_BY_LEVEL(xplevel); if ( tempxp != 0 ) { if ( tempxp > GET_XP() ) SET_XP(tempxp); // if new level XP greater than current saved XP } } DEL_XPLEVEL() { integer minxplevel = GET_MYRIAD("MINXPLEVEL"); integer xplevel = GET_XPLEVEL(); if ( xplevel > minxplevel ) { SET_XPLEVEL(xplevel--); DEBUG("Level deleted. New level: "+(string)xplevel); } else { ERROR("Unable to delete a level. Current level already: "+(string)xplevel); } integer tempxp = GET_XP_BY_LEVEL(xplevel); if ( tempxp != 0 ) SET_XP(tempxp); // FIXME PPMA XP } SET_XPLEVEL(integer amount) { integer xplevel; integer minxplevel = GET_MYRIAD("MINXPLEVEL"); integer maxxplevel = GET_MYRIAD("MAXXPLEVEL"); if ( amount < minxplevel || amount > maxxplevel ) { ERROR("Set level "+(string)amount+" out of range: "+(string)minxplevel+"-"+(string)maxxplevel); return; } xplevel = amount; integer tempxp = GET_XP_BY_LEVEL(xplevel); if ( tempxp != 0 ) SET_XP(tempxp); // set if ( xplevel < minxplevel ) xplevel = minxplevel; if ( xplevel > maxxplevel ) xplevel = maxxplevel; SET_VAL("PROGRESS","XPLEVEL",(string)xplevel); llMessageLinked(LINK_THIS,MODULE_PROGRESS,"PROGRESS|XPLEVEL="+(string)xplevel,llGetOwner()); } integer GET_XP_BY_LEVEL(integer amount ) { integer minxplevel = GET_MYRIAD("MINXPLEVEL"); integer maxxplevel = GET_MYRIAD("MAXXPLEVEL"); if ( amount >= minxplevel && amount <= maxxplevel ) { return llList2Integer(XP_BY_LEVEL,amount); } ERROR("Requested level "+(string)amount+" out of range "+(string)minxplevel+"-"+(string)maxxplevel); return 0; } // XPLEVEL integer GET_XPLEVEL() { integer xplevel = (integer)GET_VAL("PROGRESS","XPLEVEL"); integer minxplevel = GET_MYRIAD("MINXPLEVEL"); integer maxxplevel = GET_MYRIAD("MAXXPLEVEL"); if ( xplevel < minxplevel ) { xplevel = minxplevel; SET_XPLEVEL(xplevel); } if ( xplevel > maxxplevel ) { xplevel = maxxplevel; SET_XPLEVEL(xplevel); } llMessageLinked(LINK_THIS,MODULE_PROGRESS,"PROGRESS|XPLEVEL="+(string)xplevel,llGetOwner()); return xplevel; } // XP LEVEL CALCULATE_LEVEL_BY_XP() { integer i; for ( i=1; i < llGetListLength(XP_BY_LEVEL); i++ ) { integer basexp = llList2Integer(XP_BY_LEVEL,i); if ( GET_XP() >= basexp ) { SET_XPLEVEL(i); } } } // LEVEL UP - Calculate bonuses related to new level LEVELUP(integer newlevel) { // In the Myriad system, each time a character gains a new level he is given two skill points, each of which can be used to purchase a new skill at level 1 or improve an existing skill by one level. SET_SKILLPOOL ( GET_SKILLPOOL() + 2 ); // add two skill points per level // The character also gains an SFX point on every even-numbered level if the module being played supports SFX. if ( ( newlevel % 2 ) == 0 ) { // every even level SET_EFFECTPOOL ( GET_EFFECTPOOL () + 1 ); // add new SFX point } // One new health point may also be used to upgrade any one of the character's resilience lines, or saved in order to buy a box that would normally cost two points. SET_HEALTHPOOL ( GET_HEALTHPOOL() + 1 ); // add a point of health // Finally, the character earns one quarter of a statistic point to improve any one statistic with. if ( ( newlevel % 4 ) == 0 ) { // every 4th level SET_STATPOOL( GET_STATPOOL() + 1 ); // add a new stat point } } // ADD_OPPONENT_XP - add a scale of XP based on opponent's level // +2 pts if enemy 2 or more levels above, 1 point if enemy is 1 level above or below, and zero points if enemy 2 or more levels lowere ADD_OPPONENT_XP(integer opponentlevel) { integer diff = opponentlevel - GET_XPLEVEL(); integer add = 0; if ( diff >= 2 ) add = 2; if ( diff >= -1 && diff <= 1 ) add = 1; if ( add == 0 ) { OWNERSAY("No XP given for lower level opponent."); return; } OWNERSAY("You earned "+(string)add+" XP for that opponent."); ADD_XP(add); } // ADD_OPPONENT_XP_X10 // if XPSCALE = 10, multiply all the values in the XP level table by ten and use the following rule: // a monster is worth 3XP, minus 1 for every level that it is below the character's own to a minimum of zero, or plus one for every level that it is above the character's own to a maximum of ten. // ADD_OPPONENT_XP_X10(integer opponentlevel) { integer base = 3; integer add; integer diff; integer xplevel = GET_XPLEVEL(); if ( opponentlevel > xplevel ) { diff = opponentlevel - xplevel; if ( diff > 10 ) diff = 10; add = base + diff; } if ( opponentlevel < xplevel ) { diff = xplevel - opponentlevel; add = base - diff; if ( add < 0 ) add = 0; } OWNERSAY("You earned "+(string)add+" XP for that opponent."); ADD_XP(add); } /////////////////////// // PROGRESS: GRADUAL // /////////////////////// // // XPLEFT // integer GET_XPLEFT() { integer xp = (integer)GET_VAL("PROGRESS","XPLEFT"); integer minxp = GET_MYRIAD("MINXP"); integer maxxp = GET_MYRIAD("MAXXP"); if ( xp < minxp ) { xp = minxp; SET_XPLEFT(xp); } if ( xp > maxxp ) { xp = maxxp; SET_XPLEFT(xp); } llMessageLinked(LINK_THIS,MODULE_PROGRESS,"PROGRESS|XPLEFT="+(string)xp,llGetOwner()); return xp; } SET_XPLEFT(integer xp) { integer minxp = GET_MYRIAD("MINXP"); integer maxxp = GET_MYRIAD("MAXXP"); if ( xp < minxp ) xp = minxp; if ( xp > maxxp ) xp = maxxp; SET_VAL("PROGRESS","XPLEFT",(string)xp); llMessageLinked(LINK_THIS,MODULE_PROGRESS,"PROGRESS|XPLEFT="+(string)xp,llGetOwner()); } // // FIXME SPENDXP // SPENDXP() { if ( FLAG_SESSION == TRUE ) { ERROR("Cannot spend XP during play session."); return; } } // // FIXME IMPROVE_STATISTIC // FIXME - list of stats and whether or not they've been improved this session? // IMPROVE_STAT(string statname) { } // // FIXME IMPROVE_SKILL // IMPROVE_SKILL(string skillname) { } // // FIXME IMPROVE_EFFECT // IMPROVE_EFFECT(string effect) { } // // FIXME CALC_STAT_COST // integer CALC_STAT_COST(string statname) { integer statcostfactor = GET_MYRIAD("STATCOSTFACTOR"); integer cost = ( GET_STATISTIC(statname) + 1) * statcostfactor; DEBUG("Cost to increase stat "+statname+": "+(string)cost); return cost; } // // FIXME CALC_SKILL_COST // integer CALC_SKILL_COST(string skillname) { // calculate to raise existing OR buy new integer skillcostfactor = GET_MYRIAD("SKILLCOSTFACTOR"); integer cost = ( GET_SKILL(skillname) + 1) * skillcostfactor; DEBUG("Cost to increase skill "+skillname+": "+(string)cost); return cost; } // // FIXME CALC_EFFECT_COST // integer CALC_SFX_COST(string sfxname) { // calculate cost to buy new integer count = COUNT_TYPE("EFFECT"); integer effectcostbase = GET_MYRIAD("EFFECTCOSTBASE"); integer effectcostfactor = GET_MYRIAD("EFFECTCOSTFACTOR"); integer cost = effectcostbase + ( effectcostfactor * count ); DEBUG("Cost to buy new special effect ability "+sfxname+": "+(string)cost); return cost; } ////////////////////// // PROGRESS: RANDOM // ////////////////////// INCREASE_STAT(string sname) { integer rank = GET_STATISTIC(sname); SET_STATISTIC(sname,rank + 1); } integer GET_STAT_INC(string stat) { // FIXME how to verify stat? integer points = (integer)GET_VAL("STAT_INCREASE",stat); integer minstatinc = GET_MYRIAD("MINSTATINC"); integer maxstatinc = GET_MYRIAD("MAXSTATINC"); if ( points < minstatinc ) { points = minstatinc; SET_STAT_INC(stat,points); } if ( points > maxstatinc ) { points = maxstatinc; SET_STAT_INC(stat,points); } llMessageLinked(LINK_THIS,MODULE_PROGRESS,"STAT_INCREASE|"+stat+"="+(string)points,llGetOwner()); // FIXME remove unneeded link message when PPMA complete return points; } SET_STAT_INC(string statname,integer amt) { // FIXME how to verify stat names are valid? integer minstatinc = GET_MYRIAD("MINSTATINC"); integer maxstatinc = GET_MYRIAD("MAXSTATINC"); if ( amt < minstatinc ) { amt = maxstatinc; } if ( amt > maxstatinc ) { amt = minstatinc; // reset to zero and increase stat itself SET_STATISTIC(statname, GET_STATISTIC(statname) + 1 ); } SET_VAL("STAT_INCREASE",statname,(string)amt); // save new amount llMessageLinked(LINK_THIS,MODULE_PROGRESS,"SET_STAT_INCREASE|"+statname+"="+(string)amt,llGetOwner()); // FIXME remove unneeded link message when PPMA complete } INCREASE_STAT_INC(string sname) { integer rank = GET_STAT_INC(sname); SET_STAT_INC(sname,rank + 1); } INCREASE_SKILL(string skill) { integer rank = GET_SKILL(skill); integer maxskill = GET_MYRIAD("MAXSKILL"); if ( rank < maxskill ) { SET_SKILL(skill,rank + 1); RPEVENT("increased their "+skill+" skill by one."); } else { ERROR("INCREASE_SKILL("+skill+") CANNOT INCREASE PAST MAX SKILL LEVEL "+(string)maxskill); } } // SKILL INCREASES integer GET_SKILL_INC() { integer inc = (integer)GET_VAL("PROGRESS","SKILL_INCREASES"); integer minskillinc = GET_MYRIAD("MINSKILLINC"); integer maxskillinc = GET_MYRIAD("MAXSKILLINC"); if ( inc < minskillinc ) { inc = minskillinc; SET_SKILL_INC(inc); } if ( inc > maxskillinc ) { inc = maxskillinc; SET_SKILL_INC(inc); } llMessageLinked(LINK_THIS,MODULE_PROGRESS,"PROGRESS|SKILL_INCREASES="+(string)inc,llGetOwner()); // FIXME remove unneeded link message when PPMA complete return inc; } SET_SKILL_INC(integer si) { integer minskillinc = GET_MYRIAD("MINSKILLINC"); integer maxskillinc = GET_MYRIAD("MAXSKILLINC"); if ( si < minskillinc ) si = minskillinc; if ( si > maxskillinc ) si = maxskillinc; SET_VAL("PROGRESS","SKILL_INCREASES",(string)si); llMessageLinked(LINK_THIS,MODULE_PROGRESS,"PROGRESS|SKILL_INCREASES="+(string)si,llGetOwner()); // FIXME remove unneeded link message when PPMA complete } // NEW SKILLS - number of new skills earned through RANDOM skill increases since last reset integer GET_NEW_SKILLS() { integer new = (integer)GET_VAL("PROGRESS","NEW_SKILLS"); // FIXME NEWSKILLS integer minnewskills = GET_MYRIAD("MINNEWSKILLS"); integer maxnewskills = GET_MYRIAD("MAXNEWSKILLS"); if ( new < minnewskills ) { new = minnewskills; SET_NEW_SKILLS(new); } if ( new > minnewskills ) { new = maxnewskills; SET_NEW_SKILLS(new); } llMessageLinked(LINK_THIS,MODULE_PROGRESS,"PROGRESS|NEW_SKILLS="+(string)new,llGetOwner()); // FIXME remove unneeded link message when PPMA complete return new; } SET_NEW_SKILLS(integer new) { integer minnewskills = GET_MYRIAD("MINNEWSKILLS"); integer maxnewskills = GET_MYRIAD("MAXNEWSKILLS"); if ( new < minnewskills ) new = minnewskills; if ( new > maxnewskills ) new = maxnewskills; SET_VAL("PROGRESS","NEW_SKILLS",(string)new); // FIXME NEWSKILLS llMessageLinked(LINK_THIS,MODULE_PROGRESS,"PROGRESS|NEW_SKILLS="+(string)new,llGetOwner()); // FIXME remove unneeded link message when PPMA complete } integer GET_SKILLS_INCREASED(string name) { integer num = (integer)GET_VAL("SKILL_INCREASE",name); // FIXME need range checks llMessageLinked(LINK_THIS,MODULE_PROGRESS,"SKILL_INCREASE|"+name+"="+(string)num,llGetOwner()); // FIXME remove unneeded link message when PPMA complete return num; } SET_SKILLS_INCREASED(string name,integer rank) { // FIXME need range checks SET_VAL("SKILL_INCREASE",name,(string)rank); llMessageLinked(LINK_THIS,MODULE_PROGRESS,"SKILL_INCREASE|"+name+"="+(string)rank,llGetOwner()); // FIXME remove unneeded link message when PPMA complete } SKILL_FAILED(string sname) { if ( PROGRESSION != "RANDOM" ) return; // tracking skill failure only applies to random progression - ignore message integer current = GET_SKILLS_INCREASED(sname); if ( current < 4 ) { // not yet, just note it } else { // has hit 5, increase skill and stat INCREASE_SKILL(sname); // increase skill SET_SKILLS_INCREASED(sname,current + 1); } integer si = GET_SKILL_INC() + 1; SET_SKILL_INC(si); // now - 5 skill increases = new skill earned if ( si == 5 ) { SET_SKILL_INC(0); SET_NEW_SKILLS ( GET_NEW_SKILLS() + 1); RPEVENT("earned a new skill!"); } } integer GET_SIXES_BURNED() { integer sb = (integer)GET_VAL("PROGRESS","SIXES_BURNED"); // FIXME range checking llMessageLinked(LINK_THIS,MODULE_PROGRESS,"PROGRESS|SIXES_BURNED="+(string)sb,llGetOwner()); // FIXME remove unneeded link message when PPMA complete return sb; } SET_SIXES_BURNED(integer sb) { // FIXME range checking SET_VAL("PROGRESS","SIXES_BURNED",(string)sb); llMessageLinked(LINK_THIS,MODULE_PROGRESS,"PROGRESS|SIXES_BURNED="+(string)sb,llGetOwner()); // FIXME remove unneeded link message when PPMA complete } ///////////// // UTILITY // ///////////// // // DEBUG - show debug chat with wearer name for sorting // DEBUG(string dmessage) { if ( GET_FLAG("DEBUG") == TRUE ) llMessageLinked(LINK_THIS,MODULE_PROGRESS,"DEBUG|"+dmessage,llGetOwner()); } // // ERROR - show errors on debug channel with wearer name for sorting // ERROR(string emessage) { llMessageLinked(LINK_THIS,MODULE_PROGRESS,"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_PROGRESS,"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 // Progression if ( cmd == "set_progression" ) { SET_PROGRESSION(sdata); return; } // set progress method to LEVEL, GRADUAL, or RANDOM if ( cmd == "start_session" ) { START_SESSION(); return; } if ( cmd == "end_session" ) { END_SESSION(); return; } if ( cmd == "report_pools" ) { REPORT_POOLS(); return;} // used for character builder to ask player HUD for current pools // Progression API? if ( cmd == "add_xp" ) { ADD_XP(idata); return; }// ADD_XP|XP=### if ( cmd == "del_xp" ) { DEL_XP(idata); return; } // DEL_XP|XP=### if ( cmd == "add_xplevel" ) { ADD_XPLEVEL(); return; }// ADD_XPLEVEL|XPLEVEL=### if ( cmd == "del_xplevel" ) { DEL_XPLEVEL(); return; }// DEL_XPLEVEL|XPLEVEL=### // FIXME remove unneeded link message when PPMA complete all GET_* command blocks once PPMA is integrated in all HUD scripts if ( cmd == "dump_progress" ) { DUMP_PROGRESS(id); return; } // id is UUID of character builder, sent over from HUD script if ( cmd == "del_progress" ) { DEL_PROGRESS(id); return; } // id is UUID of item that requested del progress if ( cmd == "add_xp2" ) { ADD_XP2(id); return; } // add a point of total and spendable XP if ( cmd == "region_setting" && llToLower(attrib) == "progression" ) { SET_PROGRESSION(sdata); return;} if ( cmd == "set_xp" ) { SET_XP(idata); return;} if ( cmd == "set_xplevel" ) { SET_XPLEVEL(idata); return;} if ( cmd == "set_gp" ) { SET_GP(idata); return;} if ( cmd == "set_statpool" ) { SET_STATPOOL(idata); return;} if ( cmd == "set_healthpool" ) { SET_HEALTHPOOL(idata); return;} if ( cmd == "set_skillpool" ) { SET_SKILLPOOL(idata); return;} if ( cmd == "set_sfxpool" ) { SET_EFFECTPOOL(idata); return;} if ( cmd == "skill_failed" ) { SKILL_FAILED(sdata); return; } // SKILL_FAILED|SKILL=name if ( cmd == "progress" ) { // remove me later if ( llToLower(attrib) == "xp" ) { SET_XP(idata); return;} if ( llToLower(attrib) == "xplevel" ) { SET_XPLEVEL(idata); return;} if ( llToLower(attrib) == "statpool" ) { SET_STATPOOL(idata); return; } if ( llToLower(attrib) == "healthpool" ) { SET_HEALTHPOOL(idata); return; } if ( llToLower(attrib) == "skillpool" ) { SET_SKILLPOOL(idata); return; } if ( llToLower(attrib) == "sfxpool" ) { SET_EFFECTPOOL(idata); return; } return; } } // // 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_PROGRESS,"RPEVENT|"+rpevent,llGetOwner()); } // // SETUP - begin bringing the HUD online // SETUP() { XP_BY_LEVEL = [ 0,0,10,25,45,70,100,135,175,220,270,325,385,450,520,595,675,760,850,945,1045,1150,1260,1375,1495,1620,1750,1885,2025,2170,2320 ]; OWNERSAY("Progress module active."); } // // DEFAULT STATE // default { link_message(integer sender_num,integer sender,string message,key id) { if ( sender == MODULE_PROGRESS || 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