Myriad_Lite_Equipment_Server-v0.0.2-20120424.lsl
// Myriad_Lite_Equipment_Server-v0.0.1-20120124.lsl
// The Myriad RPG System was designed, written, and illustrated by Ashok Desai
// Myriad RPG licensed under the Creative Commons Attribution 2.0 UK: England and Wales
// http://creativecommons.org/licenses/by/2.0/uk/
// Myriad Lite software Copyright (c) 2011 by Allen Kerensky (OSG/SL)
// Myriad Lite licensed under the
// Creative Commons Attribution-Share Alike-Non-Commercial 3.0 Unported
// http://creativecommons.org/licenses/by-nc-sa/3.0/
// CONSTANTS - DO NOT CHANGE DURING RUN
string VERSION = "0.0.2"; // Allen Kerensky's script version
string VERSIONDATE = "20120424"; // Allen Kerensky's script yyyymmdd
integer CHAN_MYRIAD = -999; // regionwide channel for Myriad events
string CARD = "Myriad_Lite_Equipment-v0.0.1-20120424.csv"; // notecard data table
// RUNTIME GLOBALS - CAN CHANGE DURING RUN
integer HAND_MYRIAD; // llListenRemove handle for Myriad regional channel
list EQNAMES; // names of equipment loaded
list EQTYPES; // types of equipment loaded, indexed by name order
list EQCOSTS; // costs of equipment loaded, indexed by name order
list EQINFOS; // info for equipment loaded, indexed by name order
list EQRANGES; // range of item loaded, indexed by name order
list EQDAMAGES; // damage of item loaded, indexed by name order
list EQPERIODS; // time period of item loaded, indexed by name order
list EQBONUSES; // bonus using item loaded, indexed by name order
list EQRATINGS; // rating of item loaded, indexed, by name order
list EQACTIVATIONS; // activation rule for item loaded, indexed by name order
list EQEFFECTS; // special effects for item loaded, indexed by name order
integer LINE = 0; // reading line number
key QUERY = NULL_KEY; // track notecard queries
// DEBUG - show debug messages
DEBUG(string dmessage) {
llOwnerSay("DEBUG: "+dmessage);
}
// SETUP - begin
SETUP() {
if ( HAND_MYRIAD != 0 ) llListenRemove(HAND_MYRIAD); // is there already a listener? clear it
HAND_MYRIAD = llListen(CHAN_MYRIAD,"",NULL_KEY,""); // start region channel listener
DEBUG("Equipment Server "+VERSION+" "+VERSIONDATE+" loading Equipment. Please wait..."); // tell player we're waiting for data server
QUERY = llGetNotecardLine(CARD,LINE++); // ask for line from notecard and advance to next line
}
// RESET - reload
RESET() {
llResetScript(); // now reset
}
LIST_EQUIPMENT(key id) {
integer replyto = (integer)("0x"+llGetSubString((string)id,0,6)); // calculate requestor-specific chat channel to reply to
// we have to work around llRegionSay max string length 1023 characters
integer items = llGetListLength(EQNAMES); // how many total items to send?
integer count; // which item are we processing now?
string out = "EQUIPMENT|"; // start an output list
integer firstflag = TRUE; // is this first item in new list?
while (count < items ) { // do we still have items in list to send?
string name = llList2String(EQNAMES,count); // get the name of current item
if ( llStringLength(out+","+name) <= 1016) { // is our output list under the string length limit?
if ( firstflag == TRUE ) { // first item in list does not need a comma prefix
out += name; // add this item as first in the output list
firstflag = FALSE; // turn off first flag since next item won't be
} else { // not first item in list, prefix with comma
out += ","+name; // add a comma and this boon to existing list
}
} else { // output string > 1016 chars long
llRegionSay(replyto,out); // send current output string
out = "EQUIPMENT|"+name; // start a new one and add current item to that
}
count++; // done putting this item in a list, set counter to next
}
llRegionSay(replyto,out); // say last line of output
}
GET_EQUIPMENT(key id,string msg) {
integer replyto = (integer)("0x"+llGetSubString((string)id,0,6)); // calculate requestor-specific chat channel to reply to
list tokens = llParseString2List(msg,["|"],[]); // split msg into list around pipe symbols
string equipment = llList2String(tokens,1); // the name of the item to get
integer listpos = llListFindList(EQNAMES,[equipment]); // get the position of that item in the list
string reply = "EQUIPMENT"; // start output item data NO PLURAL here - we're sending 1 boon
if ( listpos != -1 ) { // was item name in the list?
reply += "|NAME="+llList2String(EQNAMES,listpos); // add name field to output
reply += "|TYPE="+llList2String(EQTYPES,listpos); // add type field to output
reply += "|COST="+llList2String(EQCOSTS,listpos); // add cost field to output
reply += "|INFO="+llList2String(EQINFOS,listpos); // add info field to output
reply += "|RANGE="+llList2String(EQRANGES,listpos); // add range field to output
reply += "|DAMAGE="+llList2String(EQDAMAGES,listpos); // add damage field to output
reply += "|PERIOD="+llList2String(EQPERIODS,listpos); // add period field to output
reply += "|BONUS="+llList2String(EQBONUSES,listpos); // add bonus field to output
reply += "|RATING="+llList2String(EQRATINGS,listpos); // add rating field to output
reply += "|ACTIVATION="+llList2String(EQACTIVATIONS,listpos); // add activation rule field to output
reply += "|EFFECTS="+llList2String(EQEFFECTS,listpos); // add effect field to output
llRegionSay(replyto,reply); // send it to requestor FIXME what if output greater than 1016 chars?
} else {
llRegionSay(replyto,"EFFECTS|ERROR=Requested equipment ("+equipment+") not found"); // item requested does not exist, return an error
}
}
SET_EQUIPMENT() {
// FIXME - do we need this?
}
// DEFAULT STATE
default {
// STATE ENTRY - called on Reset
state_entry() {
SETUP(); // show credits and start notecard data load
}
// on_rez - when rezzed to ground or from inventory as attachment during login
on_rez(integer params) {
params = 0; // LSLINT
RESET(); // force to go through state entry
}
// attach - when attached or detached from inventory or during login
attach(key id) {
id = NULL_KEY; // LSLINT
RESET(); // force to go through state entry
}
// dataserver called for each line of notecard requested
dataserver(key queryid,string data) {
if ( queryid == QUERY ) { // dataserver gave us line we asked for?
if ( data != EOF ) { // we're not at end of notecard file?
if ( llGetSubString(data,0,0) == "#" ) { // does this line start with comment mark?
QUERY = llGetNotecardLine(CARD,LINE++); // ignore comment and ask for the next line
return; // return early since we skipping comments
}
// Parse non-comment lines in keyword = value[,value,...] format
list fields = llParseString2List(data,[","],[]); // break line of text into = delimited fields
integer n = llGetListLength(fields); // how many fields in this entry?
integer i; // temporary counter
// NOTE: this mess is because items have some constant fields (name, type, cost, info) and optional fields by item type
// so we create an entire empty entry, then populate it attribute by attribute from whatever we load
// then we save it to the in-memory lists which are indexed by name
// ugly - but it avoids multiple equipment servers, one per type
string name = ""; // initialize temp item name
string type = ""; // initialize temp item type
string range = ""; // initialize temp item range
string damage = ""; // initialize temp item damage
integer cost = 0; // initialize temp item cost
string info = ""; // initialize temp item info
string period = ""; // initialize temp item period
string bonus = ""; // initialize tem item bonus
string rating = ""; // initialize temp item rating
string activation = ""; // initialize temp item activations
string effects = ""; // initialize temp item effects
for (i=0; i<n; i++ ) { // count through teach field
string attribvalpair = llStringTrim(llList2String(fields,i),STRING_TRIM); // field zero is the "command"
string attrib = llStringTrim(llList2String(llParseString2List(attribvalpair,["="],[]),0),STRING_TRIM); // attribute name
string value = llStringTrim(llList2String(llParseString2List(attribvalpair,["="],[]),1),STRING_TRIM); // value of attribute
if ( attrib == "NAME" ) name = value; // if its a name, save value to temp name
if ( attrib == "TYPE" ) type = value; // if its a type, save value to temp type
if ( attrib == "COST" ) cost = (integer)value; // if its a cost, save value to type cost
if ( attrib == "INFO" ) info = value; // if its an info, save value to temp info
if ( attrib == "RANGE" ) range = value; // if its a range, save value to temp range
if ( attrib == "DAMAGE" ) damage = value; // if its a damage, save value to temp damage
if ( attrib == "PERIOD" ) period = value; // if its a period, save value to temp period
if ( attrib == "BONUS" ) bonus = value; // if its a bonus, save value to temp bonus
if ( attrib == "RATING" ) rating = value; // if its a rating, save value to temp rating
if ( attrib == "ACTIVATION" ) activation = value; // if its an activation rule, save value to temp activation
if ( attrib == "EFFECTS" ) effects = value; // if its a special effect ability list, save value to temp effects
}
// save values to memory lists
EQNAMES = EQNAMES + [name]; // add name to end of names list
EQTYPES = EQTYPES + [type]; // add type to end of types list
EQCOSTS = EQCOSTS + [cost]; // add cost to end of costs list
EQINFOS = EQINFOS + [info]; // add info to end of infos list
EQRANGES = EQRANGES + [range]; // add range to end of ranges list
EQDAMAGES = EQDAMAGES + [damage]; // add damage to end of damages list
EQPERIODS = EQPERIODS + [period]; // add period to end of periods list
EQBONUSES = EQBONUSES + [bonus]; // add bonus to end of the bonuses list
EQRATINGS = EQRATINGS + [rating]; // add rating to end of the ratings list
EQACTIVATIONS = EQACTIVATIONS + [activation]; // add activation to end of the activations list
EQEFFECTS = EQEFFECTS + [effects]; // add effects to end of effects list
QUERY = llGetNotecardLine(CARD,LINE++); // finished with known keywords, get next line
} else { // end of notecard
DEBUG("Equipment Loaded. Equipment server ready. Free Memory: "+(string)llGetFreeMemory());
} // end if data not equal eof
} // end if query id equal
} // end if data server event
listen(integer channel,string name,key id,string msg) {
channel = 0; // LSLINT
name = ""; // LSLINT
list tokens = llParseString2List(msg,["|"],[ ]); // split msg into list around pipe symbols
string command = llList2String(tokens,0); // first field is some sort of command
if ( command == "LIST_EQUIPMENT" ) { // is this a list all boon names request
LIST_EQUIPMENT(id); // call it
return; // return early instead of processing more
}
if ( command == "GET_EQUIPMENT" ) { // GET_EQUIPMENT|string equipmentname
GET_EQUIPMENT(id,msg); // call it
return; // return early instead of processing more
}
if ( command == "SET_EQUIPMENT" ) { // is this a set equipment request
SET_EQUIPMENT(); // call it
return; // return early in case we add more later
}
}
} // end default state