Allen Kerensky"It seems you've been living two lives ..."

Myriad Lite Unopposed Test2

// Myriad_Lite_Unopposed_Test_2-v0.0.1-20131104.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/
 
// CONSTANTS - DO NOT CHANGE DURING RUN
string BASENAME = "Myriad Lite Unopposed Test2"; // base name of this script without version or date
string VERSION = "0.0.1"; // Allen Kerensky's script version
string VERSIONDATE = "20131104"; // Allen Kerensky's script yyyymmdd
integer CHANMYRIAD = -999;
integer MOD_UNOPPOSED = -1;
 
//////////////////////////////////////////////////////////////////////////////
// CONFIGURATION FOR THIS UNOPPOSED TEST
//
// TASK
// A descriptive name for the task
string TASK="Unlock the Locked Door";
 
// RPEVENT_START - a string to send as an RPEVENT when player starts - tell all
// leave empty for no RPEVENT
string RPEVENT_START = "tries to defeat the lock of an electronically-locked door";
 
// Statistic to use for the Unopposed Test
// Power, Grace, Intellect, Spirit
// Choose the one that makes sense based on the skill required for the test
string STATISTIC = "Intellect";
 
// Skill to test again
// See Myriad RPG System p.53 for many sample skill ideas
string SKILL = "Electronics";
 
// Standard Target Numbers
// Myriad RPG System p.19
// 4 = Foolproof
// 5 = Easy
// 6 = Average
// 7 = Tricky
// 8 = Difficult
// 9 = Very Hard
// 11 = Infeasible
// 13 = Superhuman
// 15 = Godlike
// 17 = Impossible
integer TARGETNUM = 6;
 
// Success Actions Recipes
// These are recipes based on Myriad Lite's Link Message formats. 
// See the Myriad Lite HUD Modules, specifically the WELL module for many examples.
// Replace the | in standard link messages with a ^ for these recipes
// Separate multiple actions with commas
// Keep it short to stay in LSL message length limits
string ONSUCCESS = "OWNERSAY|You have bypassed the electronic lock and the door can be opened.";
 
// RPEVENT_SUCCESS - a public chat message this object will say if a player succeeds.
// Leave empty for no RPEVENT event message
string RPEVENT_SUCCESS = "bypassed the door's electronic lock.";
 
// Success Actions Recipes
// These are recipes based on Myriad Lite's Link Message formats. 
// See the Myriad Lite HUD Modules, specifically the WELL module for many examples.
// Replace the | in standard link messages with a ^ for these recipes
// Separate multiple actions with commas
// Keep it short to stay in LSL message length limits
string ONFAIL = "OWNERSAY|You did not bypass the electronic door lock.";
 
// RPEVENT_FAIL - a public chat message this object will say if a player fails the task
// Leave empty for no RPEVENT message
string RPEVENT_FAIL = "failed to bypass the door's electronic lock";
 
// RETRIES
// TRUE or FALSE, retries are allowed
integer RETRIES = TRUE;
 
// TIME BETWEEN TRIES
// Number of seconds between retries
integer RETRYTIME = 10; // 10 minutes is usually good
string WAITMESSAGE = "You must wait 10 seconds between retries.";
 
// MAX RETRIES
// Max times before
integer MAX_RETRIES = 10;
string MORETRIES = "You can retry bypassing this lock.";
string NOMORETRIES = "The lock electronics short out and can no longer be bypassed.";
 
//////////////////////////////////////////////////////////////////////////////
// TEMPORARY STORAGE IN RUNTIME MEMORY
// SHOULD NOT NEED EDITING BEYOND THIS POINT.
list PLAYERS = []; // [ <playeruuid>,<timestried>,<lasttrytime> ] strided list of players accessing this task
integer HANDLE; // listenremove handle for this object's dynamic channel
integer CHANNEL; // calculated dynamic channel number for this object to listen on
 
// ABILITY TEST
// Requires ATTRIBUTE NAME, SKILL NAME
// Returns the ability test score for use by success fail, opposed rolls, etc
// See Myriad PDF page 18, Myriad Special Edition page 24
integer ABILITY_TEST(integer attribute,integer skill,integer modifiers) {
    integer highroll = 0; // clear out the highest roll
    while( attribute-- ) { // roll a dice for each point of the attribute
        integer roll = 1+(integer)llFrand(6.0); // roll this d6
        if ( roll > highroll) highroll = roll; // if this is highest roll so far, remember it
    } // finished rolling a dice for each point of the base attribute
    return highroll + skill + modifiers; // now, return the total of highest dice roll + skill value + modifiers
}
 
//
// CHECK ID to see if they pass/fail, and do retry list management - calls unopposed test
//
CHECK(key id) {    
    integer timestried; // place to hold how many times they have tried
    integer lasttime; // place to hold last time they tried
    // is player in list, get data, otherwise start data
    integer pos = llListFindList(PLAYERS,[id]); // find their current record in player list in memory
    if ( pos >= 0 ) { // they already had a record
        timestried = llList2Integer(PLAYERS,pos + 1); // get stored number of times tried
        lasttime = llList2Integer(PLAYERS,pos + 2); // get time of last try
        timestried++; // add one for this attempt
    } else { // no record so let's create and add one
        timestried = 1; // this counts as the first try
        lasttime = 0; // never tried in history
        PLAYERS = PLAYERS + [ id,timestried,lasttime ]; // add the record to the memory list
    }
    if ( timestried > MAX_RETRIES ) llInstantMessage(id,NOMORETRIES); // are they already out of tries? say so
    if ( llGetUnixTime() < ( lasttime + RETRYTIME ) ) llInstantMessage(id,WAITMESSAGE); // are they trying too soon? say so
    if ( timestried <= MAX_RETRIES && llGetUnixTime() >= ( lasttime + RETRYTIME ) ) { // if they have tries, and have waited long enough
        integer chan = (integer)("0x"+llGetSubString(id,0,6)); // calculate their player dynamic channel
        llRegionSay(chan,"UNOPPOSED_TEST2|"+TASK+"|"+STATISTIC+"|"+SKILL); // send the test request to them / their HUD
        if ( RPEVENT_START != "" ) llRegionSay(CHANMYRIAD,"RPEVENT|"+llKey2Name(id)+" "+RPEVENT_START);
    }
    // now update the player list in memory
    pos = llListFindList(PLAYERS,[id]); // where is their record, even if we just added one
    PLAYERS = llListReplaceList(PLAYERS,[id,timestried,llGetUnixTime()],pos, pos + 2); // now update the data in the player list in memory
}
 
 
DEBUG(string msg) {
    llSay(PUBLIC_CHANNEL,"DEBUG: "+msg);
}
 
ERROR(string msg) {
    llSay(PUBLIC_CHANNEL,"ERROR: "+msg);
}
 
SETUP() {
    llSetText("Easy Intellect/Electronics\nUnopposed Test2\nMyriad Lite Preview 7",<1,1,1>,1);
 
    // Setup This Object's Listener
    if ( HANDLE != 0 ) llListenRemove(HANDLE); // remove an existing handle
    CHANNEL = (integer)("0x"+llGetSubString(llGetKey(),0,6)); // calculate this object's dynamic channel number
    llListen(CHANNEL,"",NULL_KEY,""); // start a new listener on object's dynamic channel
}
 
// UNOPPOSED_TEST|<target number>|<stat name>|<skill name>|<CSV success actions>|<CSV fail actions>
// CSV success and fail actions are CSV lists action1[,action2[,...]]
// Each action is an embedded link message which uses ^ in place of the usual | used to separate fields
// Example Actions: SAY^<channel#>^<message_with_no_commas> , SHOUT^<channel#>,<message_with_no_commas>
// See the WELL module for a preset library of actions you can stack from, but any valid link message is possible
// FIXME This is a huge cheat and security hole as is without testing for valid actions by players vs. region owners
// Returns TRUE for Success and False for Fail
// UNOPPOSED_TEST2
// integer stat = amount of player's stat (0-10)
integer UNOPPOSED_TEST2(key id,integer stat,integer skill,integer mods) {
    //DEBUG("UNOPPOSED_TEST2 stat=["+(string)stat+"] skill=["+(string)skill+"] mods=["+(string)mods+"]");
    // FIXME check stat range - replace constants with MIN_STAT/MAX_STAT
    if ( stat < 0 || stat > 10 ) { ERROR("Invalid stat amount "+(string)stat+" in unopposed test. Ending unopposed test."); return FALSE;}
    // FIXME check skill range - replace constants with MIN_SKILL/MAX_SKILL
    if ( skill < 0 || skill > 7 ) { ERROR("Invalid skill amount "+(string)skill+" in unopposed test. Ending unopposed test."); return FALSE;}
    // FIXME check tskill
    integer check = ABILITY_TEST(stat,skill,mods); // calculate the player's ability test value
    integer result = FALSE;
    string acts = "" ;
    string rpevent = "";
    if ( check >= TARGETNUM ) {
        result = TRUE;
        acts = ONSUCCESS;
        rpevent = RPEVENT_SUCCESS;
    } else {  // player lost the ability test
        result = FALSE;
        acts = ONFAIL; // fail actions to player
        rpevent = RPEVENT_FAIL; // fail action rpevent to everyone
    }
    integer chan = (integer)("0x"+llGetSubString(id,0,6)); // calculate dynamic channel of player being tested
    llRegionSay(chan,acts);
    if ( rpevent != "" ) llRegionSay(CHANMYRIAD,"RPEVENT|"+llKey2Name(llGetOwnerKey(id))+" "+rpevent);
    return result;
}
 
default {
    state_entry() {
        SETUP();
    }
 
    link_message(integer sender_num,integer num,string str,key id) {
        if ( str == "UNOPPOSED_TEST2|CHECK" ) {
            CHECK(id);
        }
    }
 
    listen(integer channel,string name,key id,string message) {
        // Listen for responses from player on this objects dynamic channel
        list fields = llParseString2List(message,["|"],[]); // break into list of fields based on DIVider
        string cmd = llToUpper(llStringTrim(llList2String(fields,0),STRING_TRIM)); // assume the first field is a Myriad Lite command        
        if ( cmd == "UNOPPOSED_TEST2" ) { // UNOPPOSED_TEST2|<statamount>|<skillamount>|<modfiiers>
            integer stat = llList2Integer(fields,1);
            integer skill = llList2Integer(fields,2);
            integer mods = llList2Integer(fields,3);
            integer check = UNOPPOSED_TEST2(id,stat,skill,mods);
            if ( check == TRUE ) {
                // do more specific things if the check succeeds - unlock the door, file, etc
                llMessageLinked(LINK_THIS,MOD_UNOPPOSED,"UNOPPOSED_TEST2|SUCCESS",id);
            } else {
                // do more specific things if the check fails - set off trap, explode, sound alarm, etc
                llMessageLinked(LINK_THIS,MOD_UNOPPOSED,"UNOPPOSED_TEST2|FAILURE",id);
            }
            return;
        }
    }
 
    touch_start(integer num_detected) {
        while (num_detected--) {
            key who = llDetectedKey(num_detected); // who is clicking
            CHECK(who);
        }    
    }
}
This website uses cookies. By using the website, you agree with storing cookies on your computer. Also you acknowledge that you have read and understand our Privacy Policy. If you do not agree leave the website.More information about cookies
DokuWiki