Myriad_Lite_Armor-v0.0.7-20120826.lsl
//============================================================================
// Myriad_Lite_Armor-v0.0.7-20120826.lsl
// Copyright (c) 2012 by Allen Kerensky (OSG/SL) All Rights Reserved.
// This work is dual-licensed under
// Creative Commons Attribution (CC BY) 3.0 Unported
// http://creativecommons.org/licenses/by/3.0/
// - or -
// Modified BSD License (3-clause)
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Myriad Lite nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
// NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The Myriad RPG System was designed, written, and illustrated by Ashok Desai
// Myriad RPG System licensed under:
// Creative Commons Attribution (CC BY) 2.0 UK: England and Wales
// http://creativecommons.org/licenses/by/2.0/uk/
//============================================================================
//============================================================================
// MESSAGE FORMATS
//============================================================================
// CHANATTACH - IN - DEBUGOFF
// CHANATTACH - IN - DEBUGON
// CHANATTACH - IN - REGISTERATTACHMENTS
// CHANATTACH - IN - RESET
// CHANATTACH - IN - VERSION
// CHANATTACH - OUT - ARMORATTACH|int ARMORRATING|int ATTACHPOINT|string OBJECTNAME
// CHANATTACH - IN - ARMORBATTERY
// CHANATTACH - IN - ARMORCHECK
// CHANATTACH - OUT - ARMORDETACH|int ARMORRATING|int ATTACHPOINT|string OBJECTNAME
// CHANATTACH - IN - ARMOREFFECTBLOCKED
// CHANATTACH - IN - ARMOREFFECTHIT
// CHANATTACH - IN - ARMOREFFECTOFF
// CHANATTACH - IN - ARMORON
// CHANATTACH - IN - ARMOROFF
// CHANATTACH - IN - ARMORRECHARGE
//============================================================================
// CONSTANTS - variables which don't change over runtime
//============================================================================
// Example Armor (Myriad PDF p64, Myriad Special Edition p98)
// Archaic Armor Ratings
// 1 Soft leather, heavy cloth
// 2 Hardened leather, thick hide
// 3 Chain mail, dragon hide
// 4 Full plate mail, mithril chain
// 5 Mithril plate mail
// Modern Armor Ratings
// 1 Leather jacket
// 2 Bullet-proof vest
// 3 SWAT tactical armor
// 4 Advanced military armor
// 5 Sci-fi powered battle armor
string VERSION = "0.0.7"; // version number
string VERDATE = "20120826"; // version date
integer ARMORRATING = 1; // the *actual* amount of protection THIS piece of armor provides
string CHAN_PREFIX = "0x"; // channel prefix to convert to hexadecimal
string DIV="|"; // the divider used between fields on a Myriad Lite messages
integer MINATTACH = 1; // minimum allowed attachment point number
integer MINHUDATTACH = 31; // lower HUD attach point number
integer MAXHUDATTACH = 38; // upper HUD attach point number
integer MAXWEAR = 40; // maximum allowed avatar/inworld attachpoint number for multiattach/HUD attach cheaters
integer MAXEFFECTTIME = 3; // maximum time to show armor hit/blocked effects
integer POWERARMOR; // does this armor burn power? configured in SETUP()
//============================================================================
// RUNTIME VARIABLES - variables which should change during runtime
//============================================================================
integer FLAG_DEBUG; // see debugging messages? Configured in SETUP();
key WEARER = NULL_KEY; // holds UUID of last wearer, so we can send detach message to correct meter
integer ATTACHPOINT = 0; // the avatar position where armor attached to or detached from
integer CHANATTACH; // owner's attachment channel
integer HANDATTACH; // chat handle for attachment channel
integer ARMOR_ON; // is armor "on" and protecting when worn? configured in SETUP()
integer EFFECTTIME; // how much time is left to show armor effects
//============================================================================
// ARMORATTACH(key id) - SHOW SPECIAL ARMOR EFFECTS WHEN ATTACHING ARMOR
//============================================================================
ARMORATTACH(key id) {
integer attachpoint = llGetAttached();
if ( attachpoint < MINATTACH || ( attachpoint >= MINHUDATTACH && attachpoint <= MAXHUDATTACH ) || attachpoint > MAXWEAR ) { // valid attach point?
ERROR("Invalid armor attachment point: "+(string)attachpoint);
return;
}
WEARER = id; // save who attached this armor piece for use during detach
ATTACHPOINT = llGetAttached(); // where was this armor attached?
integer dynchan = ATTACHCHANNEL(WEARER);
// send the ATTACHARMOR to ML HUD to register that this armor piece is worn
llWhisper(dynchan,"ARMORATTACH"+DIV+(string)ARMORRATING+DIV+(string)POWERARMOR+DIV+(string)ATTACHPOINT+DIV+llGetObjectName());
// your commands go here for armor special effect when armor is attached
// Example - Particles, animated textures, sound effects, visible/invisible
// *** BEGIN your special effect code here
// ***
// *** END your special effect code here
}
//============================================================================
// ARMORBATTERY() - SHOW SPECIAL ARMOR EFFECTS WHEN CHECKING ARMOR BATTERY LEVEL
//============================================================================
ARMORBATTERY() {
// your commands go here for armor special effect when checking armor battery
// Example - Particles, animated textures, sound effects, visible/invisible
// *** BEGIN your special effect code here
// ***
// *** END your special effect code here
}
//============================================================================
// ARMORBATTERY() - SHOW SPECIAL ARMOR EFFECTS WHEN CHECKING ARMOR PROTECTION RATING
//============================================================================
ARMORCHECK() {
// your commands go here for armor special effect when checking armor protection rating
// Example - Particles, animated textures, sound effects, visible/invisible
// *** BEGIN your special effect code here
// ***
// *** END your special effect code here
}
//============================================================================
// ARMORDETACH() - tell HUD/Module Armor that we detached - called from TIMER_HEARTBEAT, not ATTACH
//============================================================================
ARMORDETACH() {
if ( llGetAttached() == 0 ) {
llWhisper((integer)(CHAN_PREFIX+llGetSubString((string)llGetOwner(),1,7)),"ARMORDETACH"+DIV+(string)ARMORRATING+DIV+(string)POWERARMOR+DIV+(string)ATTACHPOINT+DIV+llGetObjectName());
WEARER = NULL_KEY; // armor detached and reported as such, so we can forget previous wearer
ATTACHPOINT = 0; // armor detached and reported as such, so we can forget previous attach point
}
}
//============================================================================
// ARMOREFFECTBLOCKED - CHANGE ARMOR EFFECT WHEN ARMOR HIT AND BLOCKS DAMAGE
//============================================================================
ARMOREFFECTBLOCKED() {
// your commands go here for armor special effect when armor BLOCKS a hit
// Example - Particles, animated textures, sound effects, visible/invisible
// *** BEGIN your special effect code here
// ***
// *** END your special effect code here
// ***
EFFECTTIME = MAXEFFECTTIME; // load the countdown
}
//============================================================================
// ARMOREFFECTHIT() - SHOW SPECIAL ARMOR EFFECTS WHEN ARMOR HIT BUT FAILS TO BLOCK
//============================================================================
ARMOREFFECTHIT() {
// your commands go here for armor special effect when armor hit and does not block
// Example - Particles, animated textures, sound effects, visible/invisible
// *** BEGIN your special effect code here
// ***
// *** END your special effect code here
EFFECTTIME = MAXEFFECTTIME; // load the countdown
}
//============================================================================
// EFFECTOFF - RESET ARMOR TO NORMAL VIEW
//============================================================================
ARMOREFFECTOFF() {
// your commands go here to turn off armor effects
// Example - Particles, animated textures, sound effects, visible/invisible
// *** BEGIN your special effect code here
// ***
// *** END your special effect code here
// ***
}
//============================================================================
// ARMOR OFF - DEACTIVATE POWERED ARMOR
//============================================================================
ARMOROFF() {
if ( POWERARMOR == FALSE ) return;
ARMOR_ON = FALSE;
// your commands go here for armor special effect when shutting down
// Example - Particles, animated textures, sound effects, visible/invisible
// *** BEGIN your special effect code here
// ***
// *** END your special effect code here
// ***
}
//============================================================================
// ARMOR ON - ACTIVATE POWERED ARMOR
//============================================================================
ARMORON() {
ARMOR_ON = TRUE;
// your commands go here for armor special effect when starting up
// Example - Particles, animated textures, sound effects, visible/invisible
// *** BEGIN your special effect code here
// ***
// *** END your special effect code here
}
//============================================================================
// ARMORRECHARGE() - SHOW SPECIAL ARMOR EFFECTS WHEN RECHARGING ARMOR BATTERY LEVEL
//============================================================================
ARMORRECHARGE() {
// your commands go here for armor special effect when recharging
// Example - Particles, animated textures, sound effects, visible/invisible
// *** BEGIN your special effect code here
// ***
// *** END your special effect code here
}
//============================================================================
// ATTACHCHANNEL - calculate dynamic channels
//============================================================================
integer ATTACHCHANNEL(key forwho) {
// FIXME validate key does if (uuid) work in OSgrid?
if ( forwho == NULL_KEY ) return 0; // not valid
return ((integer)(CHAN_PREFIX+llGetSubString((string)forwho,1,7)));
}
//============================================================================
// DEBUG - show errors on debug channel with wearer name for sorting
//============================================================================
DEBUG(string dmessage) {
if ( FLAG_DEBUG == TRUE ) llSay(DEBUG_CHANNEL,"("+llKey2Name(WEARER)+") ARMOR: "+dmessage);
}
//============================================================================
// ERROR - show errors on debug channel with wearer name for sorting
//============================================================================
ERROR(string emessage) {
llSay(DEBUG_CHANNEL,"ERROR ("+llKey2Name(WEARER)+") ARMOR: "+emessage);
}
//============================================================================
// GETVERSION
//============================================================================
GETVERSION() {
integer dynchan = ATTACHCHANNEL(llGetOwner());
llWhisper(dynchan,"VERSION="+VERSION+DIV+"VERSIONDATE="+VERDATE+DIV+llGetObjectName());
}
//============================================================================
// RESET() - wrap the llResetScript so we can persist data if needed
//============================================================================
RESET() {
ARMOREFFECTOFF(); // stop armor effects then reset
llResetScript();
}
//============================================================================
// SETUP()
//============================================================================
SETUP() {
FLAG_DEBUG = FALSE; // do we want debugging?
ARMOR_ON = TRUE; // is power armor on and protecting by default
POWERARMOR = TRUE; // is this a piece of power armor or not?
WEARER = llGetOwner(); // set the default wearer key
// calculate a dynamic chat channel based on owner key, for where the
// wearer's ML HUD should be listening of attachment -specific events
CHANATTACH = ATTACHCHANNEL(llGetOwner());
// open a channel, listening on player HUD channel, save handle for later close if needed
if ( HANDATTACH != 0 ) llListenRemove(HANDATTACH); // close an existing listerner first
HANDATTACH = llListen(CHANATTACH,"",NULL_KEY,"");
}
//============================================================================
// DEFAULT state
//============================================================================
default {
//------------------------------------------------------------------------
// ATTACH EVENT
//------------------------------------------------------------------------
attach(key id) {
DEBUG("EVENT: attach("+(string)id+")");
if ( id == NULL_KEY ) {
ARMORDETACH();
}
// is this an attach event?
if ( id != NULL_KEY ) { // a valid key means its an attach
ARMORATTACH(id); // call the attachment fucntion
}
}
//------------------------------------------------------------------------
// CHANGED EVENT
//------------------------------------------------------------------------
changed(integer change) {
DEBUG("EVENT: changed("+(string)change+")");
if ( ( change & CHANGED_REGION ) || ( change & CHANGED_TELEPORT ) ) {
RESET();
}
}
//------------------------------------------------------------------------
// LISTEN EVENT
//------------------------------------------------------------------------
listen(integer channel,string speakername,key speakerid,string message) {
DEBUG("EVENT: listen("+(string)channel+","+speakername+","+(string)speakerid+","+message+")");
ATTACHPOINT = llGetAttached(); // get location we're attached to
list tokens = llParseString2List(message,["|"],[]);
string command = llToLower(llStringTrim(llList2String(tokens,0),STRING_TRIM));
if ( channel == CHANATTACH ) { // is this message on the attach channel?
// General Myriad Lite System Commands
if ( command == "debugoff" ) { FLAG_DEBUG = FALSE; DEBUG("off"); return; }
if ( command == "debugon" ) { FLAG_DEBUG = TRUE; DEBUG("on"); return; }
if ( command == "registerattachments" ) { ARMORATTACH(llGetOwner()); return; }
if ( command == "reset" ) { RESET(); return; }
if ( command == "version" ) { GETVERSION(); return; }
// Armor Commands
// armorattach skipped intentionally
if ( command == "armorbattery" ) { ARMORBATTERY(); return;} // show effects on armor battery level check
if ( command == "armorcheck" ) { ARMORCHECK(); return;} // show effects on armor check
// armordetach skipped intentionally
if ( command == "armoreffectblocked" ) { ARMOREFFECTBLOCKED(); return; } // did the armor block the hit too
if ( command == "armoreffecthit" ) { ARMOREFFECTHIT(); return; } // is this an armor hit?
if ( command == "armoreffectoff" ) { ARMOREFFECTOFF(); return; } // time to turn off effects?
if ( command == "armoroff" ) { ARMOROFF(); return;} // deactivate power armor
if ( command == "armoron" ) { ARMORON(); return;} // activate power armor
if ( command == "armorrecharge" ) { ARMORRECHARGE(); return;} // show effects on armor recharge
} // end if channel CHANATTACH
}
//------------------------------------------------------------------------
// ON_REZ EVENT
//------------------------------------------------------------------------
on_rez(integer start_param) {
DEBUG("EVENT: on_rez("+(string)start_param+")");
SETUP(); // call event independent SETUP code
}
//------------------------------------------------------------------------
// DEFAULT STATE ENTRY - begin our setup or call a setup block
//------------------------------------------------------------------------
state_entry() {
SETUP(); // call the event-independent SETUP code
}
} // end default
//============================================================================
// END
//============================================================================