User:Allen Kerensky/Myriad Lite/Myriad Lite Melee-Preview6.lsl

From OpenSimulator

Jump to: navigation, search

Myriad_Lite_Melee-Preview6.lsl

// Myriad_Lite_Melee-v0.0.6-20120508.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 FORMAT REFERENCE
//============================================================================
// CHANMYRIAD OUT - RPEVENT|message
// CHANATTACH IN  - REGISTERATTACHMENTS
// CHANATTACH OUT - ATTACHMELEE|int attackdice|int attachpoint|str name
// CHANATTACH OUT - DETACHMELEE|int attackdice|int attachpoint|str name
// CHANPLAYER OUT - CLOSECOMBAT|int attackdice|key victim|key attacker|str weaponname
 
//============================================================================
// GLOBAL VARIABLES
//============================================================================
string  VERSION = "0.0.6"; // version number
string  VERDATE = "20120508"; // version date
 
key WEARER = NULL_KEY; // UUID of melee weapon user
integer ATTACHPOINT = 0; // attachment point
// Melee Attack Dice
// 1D - Unarmed Combat
// 2D - Short animal claws, knife, dagger, blackjack, knuckledusters
// 3D - Long animal claws, short sword, machete, wooden baseball bat, staff
// 4D - Fire axe, long sword, katana, aluminum baseball bat, poleaxe
// 5D - Battleaxe, claymore, laser sword, daikatana, double-ended polearm
integer MELEEATTACKDICE = 4; // long sword
string DIV="|"; // Myriad message field divider
string ANIM_SWORD = "sword_strike_r"; // use built in right handed sword strike animation
integer CHANATTACH; // hold the dynamically calculated attachment channel number
integer HANDATTACH; // hold a handle to remove the attachment channel if needed
integer CHANMYRIAD = -999; // the Myriad RPEVENT channel number
integer ANIM = FALSE; // do we have permission to animate the avatar?
float WEAPON_LENGTH = 2.0; // a six-foot longsword is the default
integer SAFETY_ON = TRUE; // can this weapon be used or is it sheathed?
float FIELD_OF_ATTACK;
 
// SAFETY OFF - turn off safety and enable firing
SAFETYOFF() {
    SAFETY_ON = FALSE; // switch the safety off
    llRequestPermissions(llGetOwner(),PERMISSION_TAKE_CONTROLS|PERMISSION_TRIGGER_ANIMATION); // request permissions
}
 
// SAFETY ON - turn on safety
SAFETYON() {
    SAFETY_ON = TRUE; // switch the safety on
    llReleaseControls();
}
 
// DRAW THE WEAPON
DRAW(string hand) {
    // draw code goes here - turn copy in hand visible?
    if ( llGetAttached() == 5 && ( hand == "left" || hand == "both" ) ) {
        llRegionSay(CHANMYRIAD,llKey2Name(llGetOwner())+" draws a weapon with their left hand.");
        llOwnerSay("Left hand weapon drawn.");
        llSetLinkAlpha(LINK_SET,1.0,ALL_SIDES);        
    }
    if ( llGetAttached() == 6 && ( hand == "right" || hand == "both" ) ) {
        llRegionSay(CHANMYRIAD,llKey2Name(llGetOwner())+" draws a weapon with their right hand.");
        llOwnerSay("Right hand weapon drawn.");
        llSetLinkAlpha(LINK_SET,1.0,ALL_SIDES);        
    }
    SAFETYOFF(); // unholster and turn off safety
}
 
// SHEATHE THE WEAPON
SHEATHE(string hand) {
    // sheathe code goes here - turn copy in hand invisible?
    if ( llGetAttached() == 5 && ( hand == "left" || hand == "both" ) ) {
        llRegionSay(CHANMYRIAD,llKey2Name(llGetOwner())+" sheathes their left-hand weapon.");
        llOwnerSay("Left hand weapon sheathed.");
        llSetLinkAlpha(LINK_SET,0.0,ALL_SIDES);        
    }
    if ( llGetAttached() == 6 && ( hand == "right" || hand == "both" ) ) {
        llRegionSay(CHANMYRIAD,llKey2Name(llGetOwner())+" sheathes their right-hand weapon.");
        llOwnerSay("Right hand weapon sheathed.");
        llSetLinkAlpha(LINK_SET,0.0,ALL_SIDES);        
    }
    SAFETYON(); // turn on safety before holstering
}
 
// SETUP THE WEAPON
SETUP() {
    CHANATTACH = (integer)("0x"+llGetSubString((string)llGetOwner(),1,7)); // calculate dynamic attachment channel
    HANDATTACH = llListen(CHANATTACH,"",NULL_KEY,""); // start listening on attachment channel
    SAFETY_ON = TRUE; // safe the weapon until drawn
    SAFETYON();
    // FIELD_OF_ATTACK = PI/6; // use when sensor works
    FIELD_OF_ATTACK = PI; // use when sensor doesn't work
    llSetLinkAlpha(LINK_SET,0.0,ALL_SIDES); // turn invisble as if sheathed
}
 
//============================================================================
// DEFAULT STATE
//============================================================================
default {
    //------------------------------------------------------------------------
    // STATE_ENTRY EVENT - called on reset
    //------------------------------------------------------------------------    
    state_entry() {
        SETUP();
    }
    //------------------------------------------------------------------------
    // ON_REZ EVENT
    //------------------------------------------------------------------------
    on_rez(integer params) {
        params = 0; // LSLINT
        SETUP();
    }
 
    //------------------------------------------------------------------------
    // ATTACH EVENT
    //------------------------------------------------------------------------
    attach(key id) {
        if ( id != NULL_KEY ) { // if id not equal null key, this is an attach
            WEARER = id; // save the id we attached to
            ATTACHPOINT = llGetAttached(); // get the position we attached to
            // tell the region we're arming a weapon
            llRegionSay(CHANMYRIAD,"RPEVENT"+DIV+llKey2Name(WEARER)+" equips their "+llGetObjectName());
            integer dynchan = (integer)("0x"+llGetSubString((string)WEARER,1,7)); // calculate dynamic attach channel
            // send attach melee message to HUD which disables fist fighter
            llWhisper(dynchan,"ATTACHMELEE"+DIV+(string)MELEEATTACKDICE+DIV+(string)ATTACHPOINT+DIV+llGetObjectName());
            llRequestPermissions(id,PERMISSION_TAKE_CONTROLS|PERMISSION_TRIGGER_ANIMATION); // request permissions
        } else { // the id was null key, so this is a detach
            integer dynchan = (integer)("0x"+llGetSubString((string)WEARER,1,7)); // calculate dynamic attach channel
            if ( dynchan != 0 ) { // is channel valid
                // tell the region we're disarming
                llRegionSay(CHANMYRIAD,"RPEVENT"+DIV+llKey2Name(WEARER)+" disarms their "+llGetObjectName());
                // send detach message to HUD which re-enables fist fighter
                llWhisper(dynchan,"DETACHMELEE"+DIV+(string)MELEEATTACKDICE+DIV+(string)ATTACHPOINT+DIV+llGetObjectName());
            } else { // channel was not valid
                llSay(DEBUG_CHANNEL,"DETACH EVENT WITHOUT PREVIOUS ATTACH?"); // report the problem
            }
            WEARER = NULL_KEY; // cleanup wearer key on detach
            ATTACHPOINT = 0; // cleanup attachpoint on detach
        }
    }
    //------------------------------------------------------------------------
    // LISTEN EVENT - whisper, say, show, regionsay...
    //------------------------------------------------------------------------    
    listen(integer channel,string speakername,key speakerid,string message) {
        speakername = ""; // LSLINT
        speakerid = NULL_KEY; // LSLINT
        if ( channel == CHANATTACH ) { // did this message come in on attachment channel?
            if ( message == "REGISTERATTACHMENTS" ) { // is this a HUD asking for attachments to register?
                WEARER = llGetOwner(); // who is wielding me?
                ATTACHPOINT = llGetAttached(); // where am I attached?
                integer dynchan = (integer)("0x"+llGetSubString((string)WEARER,1,7)); // calculate wearer's dynamic attachment channel
                llWhisper(dynchan,"ATTACHMELEE"+DIV+(string)MELEEATTACKDICE+DIV+(string)ATTACHPOINT+DIV+llGetObjectName()); // tell HUD we're attached to disable fist fighter
                return;
            }
            if ( message == "DRAWLEFT" ) { DRAW("left"); return;} // draw weapon if in left hand
            if ( message == "DRAWRIGHT" ) { DRAW("right"); return;} // draw weapon in right hand
            if ( message == "DRAWBOTH" ) { DRAW("both"); return; } // draw weapon in both hands
            if ( message == "SHEATHELEFT" ) { SHEATHE("left"); return;} // sheathe left-hand weapon
            if ( message == "SHEATHERIGHT" ) { SHEATHE("right"); return;} // sheathe right-hand weapon
            if ( message == "SHEATHEBOTH" ) { SHEATHE("both"); return; } // sheathe both weapon
            if ( message == "SAFETYOFF" ) { SAFETYOFF(); return; } // unsafe the weapon
            if ( message == "SAFETYON" ) { SAFETYON(); return; } // safe the weapon
        }
    }
    //------------------------------------------------------------------------
    // RUN_TIME_PERMISSIONS EVENT - what is object allowed to do to avatar?
    //------------------------------------------------------------------------    
    run_time_permissions(integer perm) {
        if ( perm & PERMISSION_TAKE_CONTROLS ) { // can object read controls?
            llTakeControls(CONTROL_LBUTTON|CONTROL_ML_LBUTTON,TRUE,TRUE); // start watching the left mouse button in both views
        }
        if ( perm & PERMISSION_TRIGGER_ANIMATION ) { // can we also trigger animations for sword swings?
            ANIM = TRUE; // remember that we have permission now
        }
    }
    //------------------------------------------------------------------------
    // CONTROL EVENT - read arrow keys and mouse button
    //------------------------------------------------------------------------    
    control(key id,integer level,integer edge) {
        if ( SAFETY_ON == TRUE ) {
            llOwnerSay("Your weapon is sheathed, draw it!");
            llReleaseControls();
            return;
        }
        if ( id == WEARER ) { // make sure controls come from wielder
            if ( ( level & CONTROL_LBUTTON && edge & CONTROL_LBUTTON ) || ( level & CONTROL_ML_LBUTTON && edge & CONTROL_ML_LBUTTON ) ) { // if left mouse button pressed in regular or mouselook mode
                if ( ANIM == TRUE ) llStartAnimation(ANIM_SWORD); // if we can show sword swing, go ahead
                llSensor("",NULL_KEY,(AGENT|ACTIVE|PASSIVE),WEAPON_LENGTH,FIELD_OF_ATTACK); // trigger a sensor sweep for avatars within weapon range, and standing in front of us
                //llSleep(0.2); // pause to let animation run
                return; // return now to skip processing any more events we add later
            }
        }
    }
    //------------------------------------------------------------------------
    // SENSOR EVENT - what did we find?
    //------------------------------------------------------------------------    
    sensor(integer num_detected) {
        while(num_detected--) { // step through all AGENTS returned by sensor sweep
            // This is a trick to calculate a point in front of me weapon_length away
            // Thanks Mephistopheles Thalheimer (SL) for this trick
            vector A = ( llGetPos() + < WEAPON_LENGTH,0,0> * llGetRot());
            // Where is Defender
            vector D = llDetectedPos(num_detected);
            // Is defender center within 1m of my calculated point in front of me?
            // If so, my sword had a chance to hit when I swung it.
            if ( llVecDist(A,D) < 1.0 ) {         
                integer dynchan = (integer)("0x"+llGetSubString((string)llGetOwner(),0,6)); // calculate attackers HUD dynamic channel
                // send the close combat skill check message to attacker to start close combat skill check
                // attackers hud adds attacker stat and skill and sends the information to the victim to finish the opposed close combat skill check
                // we region say this so others can keep score or detect cheaters, etc
                llRegionSay(dynchan,"CLOSECOMBAT"+DIV+(string)MELEEATTACKDICE+DIV+(string)llDetectedKey(num_detected)+DIV+(string)llGetOwner()+DIV+llGetObjectName());
 
                //key who = llDetectedKey(num_detected); // who did we hit with sensor?
                //key owner = llList2Key(llGetObjectDetails(who,[OBJECT_OWNER]),0); // is this an agent/avatar for sure?
                //if ( who == owner ) { // yep, we hit an avatar
                    // tell the region an attempted attack is underway
                    llRegionSay(CHANMYRIAD,"RPEVENT"+DIV+llKey2Name(llGetOwner())+" strikes at "+llDetectedName(num_detected)+" in Close Combat!");
                //}
            }
        }
    }
    //------------------------------------------------------------------------
    // NO_SENSOR EVENT - we didn't find anything to hit
    //------------------------------------------------------------------------    
    no_sensor() {
        // we do nothing in this - but having a nosensor block avoids bugs where sensors would fail if nonsensor was missing
    }
} // end default
//============================================================================
// END
//============================================================================
Personal tools
General
About This Wiki