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