Changing from Touch event to Listen

Creating scripts
Post Reply
User avatar
Sarge Misfit
Posts: 254
Joined: Thu Mar 14, 2013 4:10 pm
Has thanked: 5 times
Been thanked: 223 times

Changing from Touch event to Listen

Post by Sarge Misfit »

I'm working on the Myriad adventure components and I am trying to figure out how to change a Touch event to a Listen. Unfortunately, I'm a bit fatigued and can't seem to get even a beginning handle on it.

Here's the section of script I would like to change, keeping in mind that I need to keep the current variables and outputs the same. No problem with adding new ones, I just have to make sure it all still works.

Code: Select all

    
    //------------------------------------------------------------------------
    // TOUCH EVENT
    //------------------------------------------------------------------------
    touch_start(integer times_touched) 
    {
        while (times_touched--) 
        { // count down through all touches in this event
            AVKEY=llDetectedKey(times_touched); // get the UUID of the toucher
            AVNAME=llDetectedName(times_touched); // get the name of the toucher
            float dist = llVecDist(llGetPos(),llList2Vector(llGetObjectDetails(AVKEY,[OBJECT_POS]),0)); // find distance between item and toucher
            if ( dist <= TOUCH_RANGE ) // is toucher within arms reach?
            { 
                if ( llListFindList(RECENT,[AVKEY]) == -1 ) // is player in recent list?
                { 
                    RECENT = [AVKEY] + RECENT; // no, add player to list
                }
                // calculate player-specific BAM dynamic channel
                TARGET= (integer)(CHAN_PREFIX + llGetSubString((string)AVKEY,-7,-1));
                llSay(TARGET, API_INADV_QUERY); // ask player if they are in adventure, must be within 10m for effect
            }
        }
    }
Btw, I plan on keeping the range check. After all, it's not very realistic to say teh proper phrase from more than a meter or so away
Living life on the wrong side of a one-track mind.

National Security Threat Level: Gnat

My site: Excelsior Station
My Kitely World: Misfit's Folly
User avatar
Dundridge Dreadlow
Posts: 616
Joined: Mon May 06, 2013 2:23 pm
Location: England
Has thanked: 590 times
Been thanked: 339 times

Re: Changing from Touch event to Listen

Post by Dundridge Dreadlow »

Without knowing the rest of your code...

Code: Select all

listen(integer channel, string AVNAME, key AVKEY, string message)
{
float dist = llVecDist(llGetPos(),llList2Vector(llGetObjectDetails(AVKEY,[OBJECT_POS]),0)); // find distance between item and toucher
            if ( dist <= TOUCH_RANGE ) // is toucher within arms reach?
            { 
                if ( llListFindList(RECENT,[AVKEY]) == -1 ) // is player in recent list?
                { 
                    RECENT = [AVKEY] + RECENT; // no, add player to list
                }
                // calculate player-specific BAM dynamic channel
                TARGET= (integer)(CHAN_PREFIX + llGetSubString((string)AVKEY,-7,-1));
                llSay(TARGET, API_INADV_QUERY); // ask player if they are in adventure, must be within 10m for effect
            }
}
I guess.
ImageImageImageImageImageImage
PS. Kitely is awesome.
User avatar
Sarge Misfit
Posts: 254
Joined: Thu Mar 14, 2013 4:10 pm
Has thanked: 5 times
Been thanked: 223 times

Re: Changing from Touch event to Listen

Post by Sarge Misfit »

Its the Myriad RP System script named BAM_Touch_Goal-Preview6.lsl

The distance check and everything else is fine. I just need for it to respond to a person saying a specific phrase rather than a touch. The reason I need to do this is because the Adventuring components are restricted to the region. My plan is to use a phrase that people can return with to continue the mission. That is, they get the mission, go to another region, complete whatever, get the "secret phrase" and can return to say that, thereby letting the mission/adventure/quest to continue.

I posted only the relevant section in the interest of space and clarity, but I guess that didn't work :-D

Here's the whole thing:

Code: Select all

// Baroun's Adventure Machine BAM_Touch_Goal-Preview6.lsl
// Copyright (c) 2012 by Baroun Tardis and 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/
 
string  VERSION = "0.0.9"; // version number
string  VERDATE = "20120704"; // version date
 
//============================================================================
// Adventure-Specific Configuration
// Task numbers are (AdvNum*100)+task, so they don't overlap between adventures
//============================================================================
 
// NPC or object-specific info
 
// Adventure-specific info
string ADVNAME          = "Test Quest"; // Adventure Name
 
// Current Task-specific info
integer ADVGOAL         = 103; // current goal
string  TASKDONETEXT    = "You've successfully touched the goal!"; // Mission complete message
string  RUMOR_TASK_DONE = " touched the BAM Touch goal."; // rumor done
string  TASKDONEUUID    = "f78027c9-e8bb-38f2-9b11-1d4e89ac10a4"; // sound byte to play
string  PRIZENAME       = "NONE"; // prize to give when mission complete

// Define quest and secret messages
string QUEST_MSG = "The butler did it";
string SECRET_MSG = "";
 
// Next Task-specific info
integer ADVTASKTDNUM    = 104; // next task to hand out when task is done
string  ADVTASKTODO     = "Return to the BAM NPC prim"; // the next goal message
string  ADVTASKTODOHINT = "Where you began"; // hint for the next goal
 
float TOUCH_RANGE = 1.5; // in meters, how close to be for touch to work arms & legs = 1.5m
integer PRIZEWAIT = 3600; // seconds to remember players who got prize?
float EVENTTIMER = 15.0; // seconds between running memory and list cleanup timed events
 
//============================================================================
// MESSAGE FORMAT REFERENCE
//============================================================================
// Ask a player HUD if the player is in an adventure - InAdv?
 
// Player responds:
// Yes in an adventure - InAdv | String AdventureName
// No, not in adventure - InAdv | NONE
 
// Task In Progress Query - Ask player what their current goal is
// NPC/Object Send Example: TaskIP?
 
// Task In Progress Response - The player Responds with current task in progress
// Player Send Example: TaskIP | AdventureGoal
 
// Task Done - Tell player they have achieved their current goal
// NPC Object Send Example: DoneTask | GoalText | TaskDone Text | PlayerUUID
 
// Add a task to the Player HUD - AddTask | TaskNumber | String Describing Task
// Add a hint for a task to the Player HUD - AddHint | TaskNumber | String Hint
 
//============================================================================
// GLOBAL CONSTANTS
//============================================================================
string MSG_STARTUP          = "Baroun's Adventure Machine is activating";
string CHAN_PREFIX          = "0x"; // prefix for calculating dynamic channels from UUIDs
string API_DIVIDER          = "|"; // The field divider within BAM packets
string API_INADV_QUERY      = "InAdv?"; // ask a player HUD if the player is in an adventure?
string API_INADV_RESPONSE   = "InAdv"; // player response to in adventure request
string API_TASKIP_QUERY     = "TaskIP?"; // what is player task-in-progress?
string API_TASKIP_RESPONSE  = "TaskIP"; // player says current task-in-progress
string API_DONETASK         = "DoneTask"; // tell player the task is done
string API_NONE             = "NONE"; // magic value for no current adventure, or no prize
string API_ADDTASK          = "AddTask"; // add a task to player HUD
string API_ADDHINT          = "AddHint"; // add a task hint to player HUD
 
//============================================================================
// GLOBAL RUNTIME
//============================================================================
list    RECENT;     // list people who recently checked this goal
list    GOTPRIZES; // list of who got prizes [UUID,unixtime]
key     AVKEY;      // key of player
string  AVNAME;     // name of player
integer BAM;        // Channel we listen on
integer TARGET;     //channel of thing we're talking to
integer HANDLE;     // hold a handle for the open listener
 
integer CHAN_REGION = -999;
integer HAND_RUMOR;
integer CHAN_RUMOR;
string  API_RUMOR_FIND = "RUMOR_SERVER_FIND";
string  API_RUMOR_FOUND = "RUMOR_SERVER_FOUND";
string  API_RUMOR_PUT = "RUMOR_PUT";
 
integer FLAG_DEBUG;
 
//============================================================================
// DEBUG
//============================================================================
DEBUG(string debugmsg) {
    if ( FLAG_DEBUG == TRUE ) llInstantMessage(llGetOwnerKey(llGetKey()),"DEBUG: "+debugmsg);
}
 
//============================================================================
// DEFAULT STATE
//============================================================================
default {
    //------------------------------------------------------------------------
    // LISTEN EVENT
    //------------------------------------------------------------------------
    listen(integer chan, string name, key id, string msg) {
        chan = 0; // LSLINT
        name = ""; // LSLINTlsl
 
        // Rumor server found, save its channel number
        if ( msg == API_RUMOR_FOUND ) {
            CHAN_RUMOR = (integer)(CHAN_PREFIX + llGetSubString((string)id,0,6));
            return;
        }
 
        // calculate the BAM dynamic channel of the person interacting with us
        TARGET= (integer)(CHAN_PREFIX + llGetSubString((string)llGetOwnerKey(id),-7,-1));
 
        list tokens = llParseString2List(msg, [API_DIVIDER], []); // split message apart around | symbols
        string command = llList2String(tokens, 0); // assign first item in list as BAM command
        string data    = llList2String(tokens, 1); // assign second item in list as BAM data for command
 
        // if they answer with the current adventure, then react accordingly
        if ( command == API_INADV_RESPONSE ) { // player responded they are in an adventure
            if ( data == ADVNAME ) { // are they in THIS adventure?
                llSay(TARGET,API_TASKIP_QUERY); // if so, ask which task in this adventure they are working on
                return; // exit early to save processing
            }
            return; // done processing "in adventure" responses, exit listen early
        }
 
        if ( command == API_TASKIP_RESPONSE ) { // player responded with their task in progress
            if ( data == (string)ADVGOAL ) { // its the task for THIS object - player has found the goal
 
                // tell player HUD the task is done! - DoneTask|(num)|(text)|UUID
                llSay(TARGET, API_DONETASK + API_DIVIDER + (string)ADVGOAL+ API_DIVIDER +TASKDONETEXT+ API_DIVIDER+ TASKDONEUUID);
                // now tell GM the task is done
                DEBUG(llKey2Name(llGetOwnerKey(id))+" (adventure "+ADVNAME+"): finished task "+(string)ADVGOAL+" ("+TASKDONETEXT+").");
 
                // Send a rumor that the player progressed in the quest
                if ( CHAN_RUMOR != 0 ) {
                    string who = llKey2Name(llGetOwnerKey(id));
                    string rumor = API_RUMOR_PUT+API_DIVIDER+who+API_DIVIDER+who+RUMOR_TASK_DONE;
                    llRegionSay(CHAN_RUMOR,rumor);
                }
 
                // The Task is Done, Distribute the Prize, if any
                if ( PRIZENAME != API_NONE && llListFindList(GOTPRIZES,[llGetOwnerKey(id)]) == -1 ) { // is there a prize at this step?
                    llGiveInventory(llGetOwnerKey(id),PRIZENAME); // give it over
                    GOTPRIZES = [ llGetOwnerKey(id), (llGetUnixTime() + PRIZEWAIT) ] + GOTPRIZES; // remember who and when
                    // tell the GM
                    DEBUG(llKey2Name(llGetOwnerKey(id))+" (adventure "+ADVNAME+") prize given: "+PRIZENAME);
                }
                // Does finishing this task trigger a new task? If so, add it and a hint to the HUD
                if ( ADVTASKTDNUM != 0 ) { // there is a "TODO" task too
                    // assign the next task to the player HUD
                    llSay(TARGET, API_ADDTASK + API_DIVIDER +(string)ADVTASKTDNUM + API_DIVIDER + ADVTASKTODO);
                    // assign the next task HINT to the player HUD
                    llSay(TARGET, API_ADDHINT + API_DIVIDER +(string)ADVTASKTDNUM + API_DIVIDER + ADVTASKTODOHINT);
                    // tell the GM the player is on the next task
                    DEBUG(llKey2Name(llGetOwnerKey(id))+" (adventure "+ADVNAME+"): Assigning next task "+(string)ADVTASKTDNUM+" ("+ADVTASKTODO+")");
                }
                return; // we're done with API_TASKIP_RESPONSE, so exit listen early in case we add more commands later
            } // if data = ADVGOAL
            return; // return early since we are done with TASKIP responses, in case we add more later
        } // end if command equal TASKIP reponse
    }
 
    //------------------------------------------------------------------------
    // STATE_ENTRY EVENT
    //------------------------------------------------------------------------
    state_entry() {
        FLAG_DEBUG = FALSE;
        DEBUG(MSG_STARTUP);
        // calculate our dynamic channel
        BAM= (integer)(CHAN_PREFIX + llGetSubString((string)llGetKey(),-7,-1));
        HANDLE = llListen(BAM,"",NULL_KEY,""); // start a listener with llremove handle
        if ( HAND_RUMOR != 0 ) llListenRemove(HAND_RUMOR);
        CHAN_RUMOR = (integer)(CHAN_PREFIX + llGetSubString((string)llGetKey(),0,6));
        HAND_RUMOR = llListen(CHAN_RUMOR,"",NULL_KEY,"");
        llRegionSay(CHAN_REGION,API_RUMOR_FIND); // send request for rumor server channel
        llSetTimerEvent(EVENTTIMER); // set a timer to manage the recent list
    }
 
    //------------------------------------------------------------------------
    // TIMER EVENT
    //------------------------------------------------------------------------
    timer() {
        // on timer, check memory left and clear recent list if needed
        integer freemem = llGetFreeMemory(); // how much memory free?
        if ( freemem < 1024 ) { // is it too little?
            DEBUG("Memory low for "+llGetObjectName()+" in "+llGetRegionName()+". Resetting RECENT list.");
            RECENT=[]; // clear the recent list
            GOTPRIZES=[]; // clear the gotPrizes list
            return; // exit timer event, no sense in processing lists further since we just emptied them
        }
        // check to see if entries in RECENT list have expired
        integer i; // temporary index number into list
        list temprecent = []; // temporary list to hold entries we want to keep
        key who; // temporary place to keep the keys we process in the lists
        integer time; // temporary place to keep the time we process in the lists
        for (i = 0; i < llGetListLength(RECENT); i += 2) { // step through strided list from begin to end
            who = llList2Key(RECENT,i); // get the UUID for this list stride
            time = llList2Integer(RECENT,i+1); // get the integer time for this list stride
            if ( llGetUnixTime() < time ) temprecent = [who,time] + temprecent; // non expired, keep this entry
        }
        RECENT = temprecent; // now, replace the RECENT list with the pruned version
        // check to see if entries in GOTPRIZES list have expired
        temprecent = []; // clear the temp list again
        for (i = 0; i < llGetListLength(GOTPRIZES); i += 2) { // step through next strided list
            who = llList2Key(GOTPRIZES,i); // get the uuid for this list stride
            time = llList2Integer(GOTPRIZES,i+1); // get the integer time for this list stride
            if ( llGetUnixTime() < time ) temprecent = [who,time] + temprecent; // non expired, keep this entry
        }
        GOTPRIZES = temprecent; // replace the gotprizes list with the pruned one        
    }
 
    //------------------------------------------------------------------------
    // TOUCH EVENT
    //------------------------------------------------------------------------
    touch_start(integer times_touched) {
        while (times_touched--) { // count down through all touches in this event
            AVKEY=llDetectedKey(times_touched); // get the UUID of the toucher
            AVNAME=llDetectedName(times_touched); // get the name of the toucher
            float dist = llVecDist(llGetPos(),llList2Vector(llGetObjectDetails(AVKEY,[OBJECT_POS]),0)); // find distance between item and toucher
            if ( dist <= TOUCH_RANGE ) { // is toucher within arms reach?
                if ( llListFindList(RECENT,[AVKEY]) == -1 ) { // is player in recent list?
                    RECENT = [AVKEY] + RECENT; // no, add player to list
                }
                // calculate player-specific BAM dynamic channel
                TARGET= (integer)(CHAN_PREFIX + llGetSubString((string)AVKEY,-7,-1));
                llSay(TARGET, API_INADV_QUERY); // ask player if they are in adventure, must be within 10m for effect
            }
        }
    }
}
//============================================================================
// END
//============================================================================
I'm was thinking that I insert llListen at some point with an if statement to check for the specific phrase (QUEST_MSG) against what the person says (SECRET_MSG), both of which I have defined with the rest of the variables at the beginning However, from what you wrote, it looks like the idea of inserting is the wrong way to go.
Living life on the wrong side of a one-track mind.

National Security Threat Level: Gnat

My site: Excelsior Station
My Kitely World: Misfit's Folly
User avatar
Dundridge Dreadlow
Posts: 616
Joined: Mon May 06, 2013 2:23 pm
Location: England
Has thanked: 590 times
Been thanked: 339 times

Re: Changing from Touch event to Listen

Post by Dundridge Dreadlow »

riiiiiiiiiiiiiiiiight, you didn't say that..
what's going on with tghe secret message in the script ??
Try something like

Code: Select all

l
isten(integer channel, string AVNAME, key AVKEY, string message)
{
    if (message==QUEST_MSG)
         {
float dist = llVecDist(llGetPos(),llList2Vector(llGetObjectDetails(AVKEY,[OBJECT_POS]),0)); // find distance between item and toucher
            if ( dist <= TOUCH_RANGE ) // is toucher within arms reach?
            { 
                if ( llListFindList(RECENT,[AVKEY]) == -1 ) // is player in recent list?
                { 
                    RECENT = [AVKEY] + RECENT; // no, add player to list
                }
                // calculate player-specific BAM dynamic channel
                TARGET= (integer)(CHAN_PREFIX + llGetSubString((string)AVKEY,-7,-1));
                llSay(TARGET, API_INADV_QUERY); // ask player if they are in adventure, must be within 10m for effect
            }
      else
          llSay(0, "You didn't say the magic word");
    }
}
(please reformat text, I just typed in the forum window)
ImageImageImageImageImageImage
PS. Kitely is awesome.
User avatar
Sarge Misfit
Posts: 254
Joined: Thu Mar 14, 2013 4:10 pm
Has thanked: 5 times
Been thanked: 223 times

Re: Changing from Touch event to Listen

Post by Sarge Misfit »

Sorry, I'm trying to do this while being a bit fatigued, which is likely most of the problem.

Basically, the way the whole thing works is that a person goes to an NPC to get the start of the mission. There can be as many goals as you want to complete the mission, with each goal being a step along the mission path. You can even set things up for alternate paths. Anyway, there are 3 scripts that are used, collision, location and touch. No particular reason to modify the touch script, it just seemed easier somehow.

So, as I said, the big problem is that these only work in the originating region, where the mission NPC is. So, my thoughts are, be able to go out of region to fulfill a goal by interacting with something like an independent NPC, or find an object that has a notecard in it or something. The key being, give the person a specific phrase. In RP context, they report back with a mission update or something similar. The SECRET_MSG is what the person is given. QUEST_MSG is what the script checks against.

Another method would be to obtain an item, or token, and then have the person give that thing to the mission NPC. But using a specific phrase seems easier.

Time for bed. Maybe I'll sleep through, have more energy and clearer head tomorrow :-)
These users thanked the author Sarge Misfit for the post:
Constance Peregrine
Living life on the wrong side of a one-track mind.

National Security Threat Level: Gnat

My site: Excelsior Station
My Kitely World: Misfit's Folly
User avatar
Sarge Misfit
Posts: 254
Joined: Thu Mar 14, 2013 4:10 pm
Has thanked: 5 times
Been thanked: 223 times

Re: Changing from Touch event to Listen

Post by Sarge Misfit »

KISS - Keep It Simply, Stupid

It turns out that all that I needed to do to get inter-region functioning was to create copies of all the objects, including the NPC controller, to the other region. Everything worked.

Not that I'm going to drop the Listen idea. That could be used for things like using a pass phrase to open mystically sealed doors and other such situation. I also think that having a Give version is also an idea. Retrieve an object and Give it to the appropriate object to unlock the next step. But, at this point, it seems to work.
These users thanked the author Sarge Misfit for the post:
Constance Peregrine
Living life on the wrong side of a one-track mind.

National Security Threat Level: Gnat

My site: Excelsior Station
My Kitely World: Misfit's Folly
User avatar
Dundridge Dreadlow
Posts: 616
Joined: Mon May 06, 2013 2:23 pm
Location: England
Has thanked: 590 times
Been thanked: 339 times

Re: Changing from Touch event to Listen

Post by Dundridge Dreadlow »

Other peoples code :P
ImageImageImageImageImageImage
PS. Kitely is awesome.
User avatar
Sarge Misfit
Posts: 254
Joined: Thu Mar 14, 2013 4:10 pm
Has thanked: 5 times
Been thanked: 223 times

Re: Changing from Touch event to Listen

Post by Sarge Misfit »

Dundridge Dreadlow wrote:Other peoples code :P
*chuckles* And the user instructions they (almost) write :lol:
Living life on the wrong side of a one-track mind.

National Security Threat Level: Gnat

My site: Excelsior Station
My Kitely World: Misfit's Folly
Post Reply