Jump to content
Erwin Solo

Support Script for Rez2 Rezzer. Rezzes on Collision or Touch

Recommended Posts

This is a support-script/trigger-script for (free-of-charge) CasperTech Rez2 script by Casper Warden. Intended use is as a doormat prim (or mesh) to rez furniture inside a house for a minimum period-of-time (float REZ_TIME), which is automatically extended if the triggering Avatar remains on the Region/SIM. Said doormat prim (or mesh) must also contain the Rez2 script, which communicates by link messages.

The benefit of this approach is that the Region/SIM is not burdened with the land impact (prims) or script load of all the furniture all the time.  Few Avatars stay in their homes more than a few hours a week.

The use case is that Avatar walks into front door of home, and furniture rezzes as Avatar walks over the (collision detect) doormat, which triggers the rezzing of furniture in the house.

By default, the furniture stays rezzed for a minimum of four hours, but that may be changed via the float REZ_TIME variable/constant, after which the furniture de-rezzes only if the triggering Avatar has left the Region/SIM. If the triggering Avatar is still on the Region/SIM, the furniture's time-to-live will be extended by another interval of float REZ_TIME.

The Avatar may also touch the doormat prim (or mesh) to initiate the rezzing operation. If the furniture is already rezzed, walking over (collision) or touching the doormat prim (or mesh) extends the rez time once again to its original value (float REZ_TIME).

Appropriate but brief messages are sent to only the most-recent Avatar to interact with the doormat prim (or mesh).

Any Avatar may trigger the doormat prim (or mesh).  No security is provided to limit action to a group or single avatar. Should the SIM/Region or land owner make too extensive use of this technique, it is conceivable that rezzing might fail due to exceeding land capacity, which situation will correct itself after float REZ_TIME expires on sufficient numbers of doormat prims (or meshes).

This is similar to the Airline and Hotel over-booking technique, which is a technique with a lot of merit, properly applied, because no-shows exist in the Airline and Hotel business and very light SIM/Region utilization is common in Second Life.  It is best to make the SIM/Region's script power available for those Avatars on the SIM/Region, and derez all the script-intensive furniture of the Avatars that are not on-SIM/Region at the time.

A griefer might trigger all the rezzers to load the SIM/Region with scripts and prims, but I think that griefers have easier ways to lag sims than run around triggering these rezzer doormats one by one.

For details on the CasperTech Rez2 API, Google: Rez2 CasperTech Wiki

Revision History

1.0.1 2018-03-23 Added a test for Avatar-on-SIM

1.0.0 2018-03-22 Initial Release

Support Script for Rez2 Rezzer. Rezzes on Collision or Touch.


float REZ_TIME = 14400.0; // 4 hours = 4.0 * 60.0 * 60.0 = 14400.0 seconds
float REPEAT_TIME = 2.0; // Interval to repeat link messages in case they were dropped
float TIMER_OFF  = 0.0; // Turns timer off.
key gkAgent = NULL_KEY; // Agent triggering script
string gsRezTimeHoursMinutes = ""; // String of REZ_TIME converted to hours and minutes


// Control Codes for sending link message to (free-of-charge) CasperTech Rez2 script by Casper Warden 

integer REZ = 10001; // Rez. Will send response code 11001 when done.
integer DEREZ = 10002; // DeRez. Will send response code 11002 when done.
integer SHOW_MENU = 10003; // Show menu dialog. Pass the avatar key as the uuid parameter.
integer EVERYONE = 10004; // Allow rez and de-rez by EVERYONE
integer GROUP = 10005; // Allow rez and de-rez by GROUP ONLY
integer OWNER = 10006; // Allow rez and de-rez by OWNER ONLY
integer OFF_TERRAFORMING = 10007; // Terraforming OFF
integer TEST = 10013; // Test
integer QUERY_REZ = 10014; // Is build currently rezzed? Responds with a RESPONSE CODE as defined below.

// Response Codes -- recieved from CasperTech Rez2 script by Casper Warden

integer CURRENTLY_REZZED = 11001; // Build is currently rezzed
integer CURRENTLY_NOT_REZZED = 11002; // Build is currently not rezzed

default // figure out whether Rez2 is in the Rezzed or Not-Rezzed state
{
    state_entry()
    {
        llVolumeDetect(TRUE);  
        llSetTimerEvent( REPEAT_TIME );
        integer iHours = llRound((REZ_TIME/3600.0)); // Total Number of Hours
        integer iMinutes = llRound( (REZ_TIME-(3600.0 * (float)iHours))/60.0 ); // Number of Minutes left over after Hours subtracted
        gsRezTimeHoursMinutes = ( ((string)iHours) + (" Hours and ") + ((string)iMinutes) + (" Minutes. ") ); 
    }
    
    on_rez (integer start_param) {llResetScript();}

    timer() 
    {
        // Link messages can fail if too many exist.  
        // Should a link message not be heard, this script
        // repeats the message a slow rate of float REPEAT_TIME 
        llMessageLinked(LINK_THIS, QUERY_REZ, "REZ2-API", NULL_KEY);
    }
    
    link_message( integer source, integer num, string str, key id )
    { 
        if ( str == "REZ2-API")
        {
            // Change to appropriate state after recieving link message 
            // that advises of current state
            
            if (num == CURRENTLY_REZZED) {state rezzed;}
            
            if (num == CURRENTLY_NOT_REZZED) {state derezzed;}
        }
    }
}

state rezzed // Stay in this state while Rezzed
{
    state_entry()
    {
        llVolumeDetect(TRUE); 
        llSetTimerEvent (REZ_TIME); 
    }
    
    on_rez (integer start_param) {llResetScript();}
    
    timer() // Go to "state derezzed" when float REZ_TIME expires
    {
        if (llGetAgentSize(gkAgent)) // Test to see if key gkAgent is still on Region/SIM
        {
            // No action by design if key gkAgent is still on Region/SIM
        }
        
        else
        {
            state derezzed; // if key gkAgent is not on SIM/Region then derez 
        }
    }
    
    collision_start( integer num_detected ) // extend rez time to full float REZ_TIME value if Avatar triggers
    { 
        gkAgent = llDetectedKey(0);
        if (llGetAgentSize(gkAgent)) // tests to ensure gkAgent is an Avatar not a non-Avatar physical object
            {
                llSetTimerEvent(REZ_TIME); // set timer back to start
                llRegionSayTo (gkAgent, PUBLIC_CHANNEL, ("Furnishings will remain rezed for " + gsRezTimeHoursMinutes));
            }
    }
    
    touch_start( integer num_detected )  // extend rez time to full float REZ_TIME value if Avatar triggers
    { 
        gkAgent = llDetectedKey(0);
        llSetTimerEvent(REZ_TIME); // set timer back to start
        llRegionSayTo (gkAgent, PUBLIC_CHANNEL, ("Furnishings will remain rezed for " + gsRezTimeHoursMinutes));
    }

}

state derezzed // this state manages rezzing and derezzing
{
    state_entry()
    {
        llVolumeDetect(TRUE); 
        llSetTimerEvent(REPEAT_TIME);
    }

    on_rez (integer start_param) {llResetScript();}
    
    timer() 
    {
        // Link messages can fail if too many exist.  
        // Should a link message not be heard, this script
        // repeats the message a slow rate of float REPEAT_TIME 
        llMessageLinked(LINK_THIS, DEREZ, "REZ2-API", NULL_KEY);
    }

    link_message( integer source, integer num, string str, key id )
    { 
        if ( str == "REZ2-API")
        {
            if (num == CURRENTLY_NOT_REZZED) 
            {
                llSetTimerEvent(TIMER_OFF); // if derezz is confirmed stop timer
                llRegionSayTo (gkAgent, PUBLIC_CHANNEL, "Furnishings are now fully de-rezzed.");
            }
            
            if (num == CURRENTLY_REZZED ) 
            {
                llRegionSayTo (gkAgent, PUBLIC_CHANNEL, ("Furnishings are now fully rezzed and will remain so for " + gsRezTimeHoursMinutes));
                state rezzed;
            }
        }
    }
    
    collision_start( integer num_detected ) // Trigger rezzing if Avatar triggers
    { 
        gkAgent = llDetectedKey(0);
        if (llGetAgentSize(gkAgent)) // tests to ensure gkAgent is an Avatar not a non-Avatar physical object
            {
                // Link messages can fail if too many exist.  
                // Should this link message not be heard, 
                // the avatar will just have to trigger it again
                llMessageLinked(LINK_THIS, REZ, "REZ2-API", NULL_KEY);
            }
    }
    
    touch_start( integer num_detected ) // Trigger rezzing if Avatar triggers
    { 
        gkAgent = llDetectedKey(0);
        // Link messages can fail if too many exist.  
        // Should this link message not be heard, 
        // the avatar will just have to trigger it again
        llMessageLinked(LINK_THIS, REZ, "REZ2-API", NULL_KEY);
    }
}

 

  • Like 2

Share this post


Link to post
Share on other sites

Looks good. Consider a menu and selectable different time-to-Rez-for options.

If this is for a rental scenario, you may want to consider checking if Avatar is in the rental group (or if it is the same Avatar who rented).

The community may be curious as to the scenario where someone only wants their furniture rezzed when they are at home.

Be aware that if you use this with Mesh, Mesh will contribute to LI even on temp-Rez.

That API looks good, thanks for posting this.

  • Like 1

Share this post


Link to post
Share on other sites

My current application is a roleplay Region/SIM that I own as estate owner.

Scenario A.  The role play SIM has several elaborate roleplay areas (call them A, B, and C) that are only used for infrequent scenes, but are necessary for the overall ambiance.  Also, the nature of the roleplay is that areas A, B, and C are not used at the same time, for they are different chapters in the story.  The rez-on-use technique provided by this script allows me to maintain or even increase the sophistication of areas A, B, and C without burdening the SIM when the areas are not in use.

Scenario B.  There are rentals.  Most of the script load in the SIM comes from the furniture in the rentals, but Avatars seem not to hang around in their rentals very much, except for intimate role play.  I am experimenting with furnishing the houses myself as the default alternative for the renters.  The flexibility of Rez2 will make it easy to delete/move/change a piece or two of furniture if the renter prefers their own bed, for example, and the walls have plenty of room for their personal photographs/artwork.  Looking at the furnishings of my current renters, I think I could provide furnishings of more ambiance than they do, with little SIM impact because with the Rez2 support script; the furnishings will only be there the 5%+/- of the time that they are actually in their houses.  If a renter prefers to completely furnish their own place, it is easy enough for me to turn off the scripts in the welcome mat rezzer in their unit for the duration of their rental.  There are only a dozen or so different rental unit styles, and their default furnishings will be identical.  Thus, the caching performed by the Second Life Server will aide rezzing performance.  If due to the time of day, SIM occupancy is high, the likelihood is that the same mesh-and-textures to-be-rezzed already exist on SIM.   Conversely, if traffic is low, the spike in rezzing activity occurs on a lightly loaded SIM.

Group Tags and restrictions.  People seem to have trouble remembering to wear their group tags, and getting lots of "it is not working" IMs from people who forget to wear their group tags is more work for me than dealing with the relatively infrequent problem of someone camping out and overstaying their rent. If group-tag checking is important to someone else, the script is open source so they can add that.  I am sure you are aware that LsL can only check for the active group tag.  LsL cannot test non-active group membership, though a scripter may cache UUIDs of Avatars who remembered to wear their group tag long ago.  When the UUID cache misses, it then becomes difficult to convince the avatar that the problem is them not wearing their group tag, because protests of "it used to work without my tag" are true, and one must explain cache hits and cache misses.  

Temp Rez.  I'm not using 'temp rez' in the sense of http://wiki.secondlife.com/wiki/PRIM_TEMP_ON_REZ

Menus.  I want to keep it simple for the casual user.  I think the test for avatar-on-SIM before derezzing provides enough automation.  Extensive menus are available from the Rez2 script, and the owner of the welcome mat prim/mesh can make those menus available with the usual Owner/Group/Everyone options.  For my application, I don't want to present a menu to the users.  

  • Like 3

Share this post


Link to post
Share on other sites

Okay, have now tested this with menus for Owner, Group, and Everyone.  The menus and Owner/Group/Everyone are provided by the Rez2 script.  This support script just gets out of the way.  If the Avatar changes the Rez/DeRez state of the build, this script needs to know it.  So, when an Avatar touches the doormat prim (or mesh), this script sleeps for float SLEEP_TIME and then tests the state of the Rez2 script via the Rez2 API.  If the Avatar keeps fiddling with the Rez2 menus, this script repeats its sleep and state-test.  For my application, only the owner will need control of the Rez2, but Rez2 does allow the owner to provide limited menus to other Avatars via Owner/Group/Everyone rules.  Using an llSleep() feels primitive but it gets the job done.  The Rez2 API just reports back rezzed or not; no info is available on the Rez2 menu actions.

Rev. 1.0.2 Gets out of the way for Rez2 menu interations

float REZ_TIME = 14400.0; // 4 hours = 4.0 * 60.0 * 60.0 = 14400.0 seconds
float REPEAT_TIME = 5.0; // Interval to repeat link messages in case they were dropped
float TIMER_OFF  = 0.0; // Turns timer off.
float SLEEP_TIME = 60.0; // Sleep time while Avatar is working Rez2 menus
key gkAgent = NULL_KEY; // Agent triggering script
string gsRezTimeHoursMinutes = ""; // String of REZ_TIME converted to hours and minutes

// Control Codes for sending link message to (free-of-charge) CasperTech Rez2 script by Casper Warden 

integer REZ = 10001; // Rez. Will send response code 11001 when done.
integer DEREZ = 10002; // DeRez. Will send response code 11002 when done.
integer SHOW_MENU = 10003; // Show menu dialog. Pass the avatar key as the uuid parameter.
integer EVERYONE = 10004; // Allow rez and de-rez by EVERYONE
integer GROUP = 10005; // Allow rez and de-rez by GROUP ONLY
integer OWNER = 10006; // Allow rez and de-rez by OWNER ONLY
integer OFF_TERRAFORMING = 10007; // Terraforming OFF
integer TEST = 10013; // Test
integer QUERY_REZ = 10014; // Is build currently rezzed? Responds with a RESPONSE CODE as defined below.

// Response Codes -- recieved from CasperTech Rez2 script by Casper Warden

integer CURRENTLY_REZZED = 11001; // Build is currently rezzed
integer CURRENTLY_NOT_REZZED = 11002; // Build is currently not rezzed

default // figure out whether Rez2 is in the Rezzed or Not-Rezzed state
{
    state_entry()
    {
        llVolumeDetect(TRUE);  
        llSetTimerEvent( REPEAT_TIME );
        integer iHours = llRound((REZ_TIME/3600.0)); // Total Number of Hours
        integer iMinutes = llRound( (REZ_TIME-(3600.0 * (float)iHours))/60.0 ); // Number of Minutes left over after Hours subtracted
        gsRezTimeHoursMinutes = ( ((string)iHours) + (" Hours and ") + ((string)iMinutes) + (" Minutes. ") ); 
    }
    
    on_rez (integer start_param) {llResetScript();}

    timer() 
    {
        // Link messages can fail if too many exist.  
        // Should a link message not be heard, this script
        // repeats the message a slow rate of float REPEAT_TIME 
        llMessageLinked(LINK_THIS, QUERY_REZ, "REZ2-API", NULL_KEY);
    }
    
    link_message( integer source, integer num, string str, key id )
    { 
        if ( str == "REZ2-API")
        {
            // Change to appropriate state after recieving link message 
            // that advises of current state
            
            if (num == CURRENTLY_REZZED) {state rezzed;}
            
            if (num == CURRENTLY_NOT_REZZED) {state derezzed;}
        }
    }
}

state rezzed // Stay in this state while Rezzed
{
    state_entry()
    {
        llVolumeDetect(TRUE); 
        llSetTimerEvent (REZ_TIME); 
    }
    
    on_rez (integer start_param) {llResetScript();}
    
    timer() // Go to "state derezzed" when float REZ_TIME expires
    {
        if (llGetAgentSize(gkAgent)) // Test to see if key gkAgent is still on Region/SIM
        {
            // No action by design if key gkAgent is still on Region/SIM
        }
        
        else
        {
            state derezzed; // if key gkAgent is not on SIM/Region then derez 
        }
    }
    
    collision_start( integer num_detected ) // extend rez time to full float REZ_TIME value if Avatar triggers
    { 
        gkAgent = llDetectedKey(0);
        if (llGetAgentSize(gkAgent)) // tests to ensure gkAgent is an Avatar not a non-Avatar physical object
            {
                llSetTimerEvent(REZ_TIME); // set timer back to start
                llRegionSayTo (gkAgent, PUBLIC_CHANNEL, ("Furnishings will remain rezed for " + gsRezTimeHoursMinutes));
            }
    }
    
    touch_start( integer num_detected )  // Avatar may be using Rez2 menus.  Wait and then reset to learn whether Avatar rezzed or de-rezzed via Rez2 menus.
    { 
        llSleep(SLEEP_TIME); // Sleep float SLEEP_TIME for Avatar to finish using Rez2 menus.
        llResetScript(); // Reset to initiate state-query process in default state
    }

}

state derezzed // this state manages rezzing and derezzing
{
    state_entry()
    {
        llVolumeDetect(TRUE); 
        llSetTimerEvent(REPEAT_TIME);
    }

    on_rez (integer start_param) {llResetScript();}
    
    timer() 
    {
        // Link messages can fail if too many exist.  
        // Should a link message not be heard, this script
        // repeats the message a slow rate of float REPEAT_TIME 
        llMessageLinked(LINK_THIS, DEREZ, "REZ2-API", NULL_KEY);
    }

    link_message( integer source, integer num, string str, key id )
    { 
        if ( str == "REZ2-API")
        {
            if (num == CURRENTLY_NOT_REZZED) 
            {
                llSetTimerEvent(TIMER_OFF); // if derezz is confirmed stop timer
                llRegionSayTo (gkAgent, PUBLIC_CHANNEL, "Furnishings are now fully de-rezzed.");
            }
            
            if (num == CURRENTLY_REZZED ) 
            {
                llRegionSayTo (gkAgent, PUBLIC_CHANNEL, ("Furnishings are now fully rezzed and will remain so for " + gsRezTimeHoursMinutes));
                state rezzed;
            }
        }
    }
    
    collision_start( integer num_detected ) // Trigger rezzing if Avatar triggers
    { 
        gkAgent = llDetectedKey(0);
        if (llGetAgentSize(gkAgent)) // tests to ensure gkAgent is an Avatar not a non-Avatar physical object
            {
                // Link messages can fail if too many exist.  
                // Should this link message not be heard, 
                // the avatar will just have to trigger it again
                llMessageLinked(LINK_THIS, REZ, "REZ2-API", NULL_KEY);
            }
    }
    
    touch_start( integer num_detected )  // Avatar may be using Rez2 menus.  Wait and then reset to learn whether Avatar rezzed or de-rezzed via Rez2 menus.
    { 
        llSleep(SLEEP_TIME); // Sleep float SLEEP_TIME for Avatar to finish using Rez2 menus.
        llResetScript(); // Reset to initiate state-query process in default state
    }

}

 

  • Like 2

Share this post


Link to post
Share on other sites

 

From the other thread:

Rezzing mesh assets is pretty heavy on the region, and can lead to rez queueing. This will deffo cause some issues if a lot of mesh is rezzed at once.

It is bad practise to rez things where you don't need really need to, remember those temp rezzers of ye olde days? Granted this is less bad but still not something I'd advice. Also some furniture will reset on rez, and load their configuration all over again. 

Also be mindful of the fact that simulators have a mesh cache of their own, hence when rezzing a new heavy mesh asset the first time takes longer than rezzing one right afterwards. This cache is cleaned automatically if the assets do not remain in the region whenever their expiration time is reached.

Also, scripts compiled in mono have a small performance hit when brought into a region in any sort. It's why putting mono scripts in bullets is a no no in most combat community. Now granted this thing doesn't rez at a rate guns do, but furniture often has a multitude of scripts in them.

This is probably gonna piss off your neighbours more than having some scripts idling, because not only will the sim lag when an avatar teleports in, if shortly after they also automatically rez like 30 pieces of furniture at once it's gonna be pain and you're gonna have another sim impact.

These are my two cents as someone who's scripting deals with rezzing a lot.

    timer() // Go to "state derezzed" when float REZ_TIME expires
    {
        if (llGetAgentSize(gkAgent)) // Test to see if key gkAgent is still on Region/SIM
        {
            // No action by design if key gkAgent is still on Region/SIM
        }
        
        else
        {
            state derezzed; // if key gkAgent is not on SIM/Region then derez 
        }
    }

This bit is kinda bad brackets are ugly, ideally you want either of these: 

	timer() // Go to "state derezzed" when float REZ_TIME expires
	{
		if (llGetAgentSize(gkAgent) == ZERO_VECTOR) // Test to see if key gkAgent is still on Region/SIM
		{
			state derezzed; // if key gkAgent is not on SIM/Region then derez 
		}
	}

Without having to use ZERO_VECTOR:

	timer() // Go to "state derezzed" when float REZ_TIME expires
	{
		if (llGetAgentSize(gkAgent)) return;
		state derezzed;     // if key gkAgent is not on SIM/Region then derez 
	}

Unnecessary else clausules aren't really a good thing.

I'd also not define things like TIMER_OFF, that's just wasting 16 bytes where 0 is clear enough what it does. I'd also not define all the control codes you're not using. All of em waste of 16 bytes per integer! I'd really suggest looking to optimize memory usage especially as mono's memory usage is dynamic. While it has an upper limit of 64kb, it will allocate/use only what it needs. So unless you use it or it has an advantage like readability don't define variables.

  • Thanks 1

Share this post


Link to post
Share on other sites
On 3/24/2018 at 5:30 PM, Love Zhaoying said:

Was there a question or feedback request in your last post? 

No, this is a script library.  This was an open source contribution to the community.  Nothing more; nothing less.  

I've been using this approach for a few weeks now and it has really cut down on the script load on my Region/SIM with no ill effects.  

I'm certainly not claiming this technique is good for every application, but its been great for mine. 

Some people seem concerned about unused declarations for the Rez2 API.  Having the Rez2 API already typed in is convenient for me when I want to modify the script to do something else. If I don't use one of them, the compiler removes them from the run time image automatically.  

  • Like 1
  • Thanks 1

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...