User:Allen Kerensky/Myriad Lite Preview4/Myriad Lite Armor v0.0.4 20110904

From Second Life Wiki
Jump to navigation Jump to search

Myriad Lite Armor v0.0.4 20110904

<lsl> //============================================================================ // Myriad Lite Armor v0.0.4 20110904 // Copyright (c) 2011 By Allen Kerensky (OSG/SL) // The Myriad RPG System was designed, written, and illustrated by Ashok Desai // Myriad is published under a: // Creative Commons License (Attribution 2.0 UK: England and Wales) // Myriad Lite Armor is published under a: // Creative Commons License Attribution-NonCommercial-ShareAlike 3.0 Unported //============================================================================

//============================================================================ // MESSAGE FORMATS //============================================================================ // CHANATTACH - IN - REGISTERATTACHMENTS // CHANATTACH - OUT - ATTACHARMOR|int ARMORRATING|int ATTACHPOINT|string OBJECTNAME // CHANATTACH - OUT - DETACHARMOR|int ARMORRATING|int ATTACHPOINT|string OBJECTNAME // CHANATTACH - IN - ARMORHIT // CHANATTACH - IN - ARMORBLOCKED

//============================================================================ // 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 integer ARMORRATING = 1; // the *actual* amount of protection THIS piece of armor provides integer MINARMOR = 1; // the minimum amount of protection a piece of armor can offer, checked by HUD integer MAXARMOR = 5; // the maximum amount of protection a piece of armor can offer, checked by HUD string DIV="|"; // the divider used between fields on a Myriad Lite messages integer MINATTACHPOINT = 1; // minimum allowed attachment point number integer MAXATTACHPOINT = 30; // maximum allowed avatar/inworld attachpoint number for multiattach/HUD attach cheaters integer MAXEFFECTTIME = 3; // maximum time to show armor hit/blocked effects integer POWERARMOR = FALSE; // does this armor burn power? integer MAXBATTERY = 3600; // how many seconds can armor run before recharge?

//============================================================================ // RUNTIME VARIABLES - variables which should change during runtime //============================================================================ key OWNER = NULL_KEY; // holds UUID of owner 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 CHANOWNER; // the chat channel the owner's ML HUD should be listening on integer HANDOWNER; // a chat channel handle to remove the listener with later integer CHANATTACH; // owner's attachment channel integer HANDATTACH; // chat handle for attachment channel integer FLAG_DEBUG = FALSE; // show debug messages or not? integer ARMOR_ON = TRUE; // is armor "on" and protecting? integer BATTERY; // current charge left for power armor integer EFFECTTIME; // how much time is left to show armor effects

//============================================================================ // DEBUG - show debug chat with wearer name for sorting //============================================================================ DEBUG(string dmessage) {

   if ( FLAG_DEBUG == TRUE ) { // debugging?
       llSay(DEBUG_CHANNEL,"DEBUG ("+llKey2Name(llGetOwner())+"): "+dmessage);
   }

}

//============================================================================ // ERROR - show errors on debug channel with wearer name for sorting //============================================================================ ERROR(string emessage) {

   llSay(DEBUG_CHANNEL,"ERROR ("+llKey2Name(llGetOwner())+"): "+emessage);

}

//============================================================================ // EFFECTHIT() - SHOW SPECIAL ARMOR EFFECTS WHEN ARMOR HIT BUT FAILS TO BLOCK //============================================================================ EFFECTHIT() {

   // your commands go here for armor special effect when armor hit and does not block
   // end of special effects
   EFFECTTIME = MAXEFFECTTIME; // load the countdown

}

//============================================================================ // EFFECTBLOCKED - CHANGE ARMOR EFFECT WHEN ARMOR HIT AND BLOCKS DAMAGE //============================================================================ EFFECTBLOCKED() {

   // your commands go here for armor special effect when armor BLOCKS a hit
       
   // end of special effects
   EFFECTTIME = MAXEFFECTTIME; // load the countdown

}

//============================================================================ // EFFECTOFF - RESET ARMOR TO NORMAL VIEW //============================================================================ EFFECTOFF() {

   // your commands go here to turn off armor effects
   // end of armor reset

}

//============================================================================ // ARMOR ON - ACTIVATE POWERED ARMOR //============================================================================ ARMORON() {

   if ( POWERARMOR == TRUE && BATTERY < 0 ) {
       llOwnerSay("Armor out of power. Recharge.");
       return;
   }
   ARMOR_ON = TRUE;
   // your code here
   llSetLinkAlpha(LINK_SET,1.0,ALL_SIDES);
   if ( POWERARMOR == TRUE ) llSetTimerEvent(1.0); // run a battery drain timer

}

//============================================================================ // ARMOR OFF - DEACTIVATE POWERED ARMOR //============================================================================ ARMOROFF() {

   ARMOR_ON = FALSE;
   llOwnerSay("Power armor shutting down.");
   // your code here
   llSetLinkAlpha(LINK_SET,0.0,ALL_SIDES);

}

//============================================================================ // CHECK BATTERY //============================================================================ CHECKBATTERY() {

   llOwnerSay("Armor battery level: "+(string)BATTERY+" of "+(string)MAXBATTERY+" total.");

}

//============================================================================ // RECHARGE POWER ARMOR BATTERY //============================================================================ RECHARGE() {

   // TODO Partial Recharges?
   BATTERY = MAXBATTERY;
   llOwnerSay("Armor recharged.");

}

//============================================================================ // GLOBAL SETUP() //============================================================================ SETUP() {

   // calculate a dynamic chat channel based on owner key, for where the
   // wearer's ML HUD should be listening of attachment -specific events
   CHANATTACH = (integer)("0x"+llGetSubString((string)llGetOwner(),1,7));
   // open a channel, listening on player HUD channel, save handle for later close if needed
   HANDATTACH = llListen(CHANATTACH,"",NULL_KEY,"");
   if ( POWERARMOR == TRUE ) BATTERY = MAXBATTERY; // charge the battery to full
   llSetLinkAlpha(LINK_SET,1.0,ALL_SIDES); // show the armor

}

//============================================================================ // DEFAULT //============================================================================ default {

   //------------------------------------------------------------------------
   // DEFAULT STATE ENTRY - begin our setup or call a setup block
   //------------------------------------------------------------------------
   state_entry() {
       SETUP(); // call the event-independent SETUP code
   }
   //------------------------------------------------------------------------
   // DEFAULT ON_REZ
   //------------------------------------------------------------------------
   on_rez(integer start_param) {
       SETUP(); // call event independent SETUP code        
   }   
   //------------------------------------------------------------------------
   // DEFAULT ATTACH - Called for detach too
   //------------------------------------------------------------------------
   attach(key id) {
       SETUP(); // call event-independent SETUP code
       // is this an attach event or detach event?
       if ( id != NULL_KEY ) { // a valid key means its an attach
           WEARER = id; // save who attached this armor piece for use during detach
           ATTACHPOINT = llGetAttached(); // where was this armor attached?
           // this should NOT be necessary, since it should match CHANPLAYER
           // however, armor can be dropped! So, wearer may NOT be owner. Need changed block?
           integer dynchan = (integer)("0x"+llGetSubString((string)WEARER,1,7));
           // Send ATTACHARMOR message to WEARER HUD
           llWhisper(dynchan,"ATTACHARMOR"+DIV+(string)ARMORRATING+DIV+(string)ATTACHPOINT+DIV+llGetObjectName());
       } else { // else the id equals NULL_KEY which happens for detach
           // calculate dynamic channel for person last wearing armor piece
           integer dynchan = (integer)("0x"+llGetSubString((string)WEARER,1,7));
           if ( dynchan != 0 ) { // did the dynamic channel check give us usable channel number <0 or >0 but not actually 0?
               // Send DETACHARMOR message to previous wearer's HUD
               llWhisper(dynchan,"DETACHARMOR"+DIV+(string)ARMORRATING+DIV+(string)ATTACHPOINT+DIV+llGetObjectName());
           } else { // the dynamic channel was 0?
               // how did we get in this mess? a detach without an attach. Report error. Design failure somewhere. THIS SHOULD NEVER HAPPEN.
               DEBUG("DETACH EVENT WITHOUT PREVIOUS ATTACH?");
           } // end of if dynchan not equal zero
           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
       } // end of if id not equal null key
   }
   //------------------------------------------------------------------------
   // DEFAULT CHANGED
   //------------------------------------------------------------------------
   changed(integer change) {
       if ( change & CHANGED_OWNER ) { // if armor has a new owner from take-from-ground or copy, resetup
           SETUP(); // call event-independent setup code, in this case to update channels
       }
   }    
   //------------------------------------------------------------------------
   // DEFAULT LISTEN
   //------------------------------------------------------------------------
   listen(integer channel,string speakername,key speakerid,string message) {
       ATTACHPOINT = llGetAttached(); // get location we're attached to
       if ( channel == CHANATTACH ) { // is this message on the attach channel?
           if ( message == "ARMORHIT" ) { // is this an armor hit?
               EFFECTHIT(); // turn on armor hit effects
               return; // message processed, exit early
           }
           if ( message == "ARMORBLOCKED" ) { // did the armor block the hit too
               EFFECTBLOCKED(); // turn on armor block effects
               return; // message processed, exit early
           }
           // ML HUD sent a request for any attached items
           if ( ( message == "REGISTERATTACHMENTS" ) && ( ATTACHPOINT >= MINATTACHPOINT ) && ( ATTACHPOINT <= MAXATTACHPOINT ) ) {
               WEARER = llGetOwner(); // get armor owner BUG: what if owner not equal wearer?
               // calculate the dynamic channel of the wearer
               integer dynchan = (integer)("0x"+llGetSubString((string)WEARER,1,7));
               // send the ATTACHARMOR to ML HUD to register that this armor piece is worn
               llWhisper(dynchan,"ATTACHARMOR"+DIV+(string)ARMORRATING+DIV+(string)ATTACHPOINT+DIV+llGetObjectName());
               return; // message processed, exit early
           } // end of if message equal REGISTERATTACHMENTS            
           if ( message == "ARMORON" ) { ARMORON(); return;} // activate power armor
           if ( message == "ARMOROFF" ) { ARMOROFF(); return;} // deactivate power armor
           if ( message == "RECHARGE" ) { RECHARGE(); return;} // recharge power armor battery?
           if ( message == "CHECKBATTERY" ) { CHECKBATTERY(); return;} // check battery level
       } // end if channel CHANATTACH
   }    
   //------------------------------------------------------------------------
   // TIMER CALLED TO TURN OFF THE SPECIAL EFFECTS
   //------------------------------------------------------------------------
   timer() {
       EFFECTTIME--;
       if ( EFFECTTIME <= 0 ) { 
           EFFECTOFF(); // turn off special effects
           EFFECTTIME=0; // make it zero anyway
       } // timer expired, turn off effect
       if ( POWERARMOR == TRUE && ARMOR_ON == TRUE ) {
           BATTERY--; // remove some battery
           if ( BATTERY <= 0 ) {
               llOwnerSay("Armor battery drained. Shutting down.");
               ARMOROFF(); // turn off armor
           }
       }
       if ( EFFECTTIME <= 0 || ARMOR_ON == FALSE ) llSetTimerEvent(0.0); // all timers done, stop timer events
   } // end timer

} // end default //============================================================================ // END //============================================================================ </lsl>