Jump to content

Erwin Solo

Resident
  • Posts

    1,212
  • Joined

  • Last visited

  • Days Won

    4

Everything posted by Erwin Solo

  1. Well, as long as we are getting our post count up. I'm sure there is some way to do RAW files.
  2. Well, its not clear which forum this should go in. I want to edit my region's raw file in Photoshop. That used to work. Now I have a photoshop subscription and so the software is always current. Photoshop doesn't recognize the RAW layers or even the grid size. If the topic is not familiar to you, RAW files are described here: http://wiki.secondlife.com/wiki/Tips_for_Creating_Heightfields_and_Details_on_Terrain_RAW_Files . Should I be using a different tool? In addition to Photoshop I can also work in Blender or Maya LT or MudBox, or I can learn something new. I looked on YouTube, but the videos there are about the way things used to work in PhotoShop. P.S. I think I'll throw the words terraform and terraforming in here just to help the search engines.
  3. 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 } }
  4. 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.
  5. 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); } }
  6. I'll second that. I do it quite often. Test the uploads on the beta grid and upload the finished product on the production grid.
  7. Please just google "caspertech rez2 wiki"
  8. Well, the jira entry got triaged and accepted: https://jira.secondlife.com/browse/BUG-214737
  9. Question: Am I overlooking anything? Background: I believe that the llTeleportAgentGlobalCoords( key agent, vector global_coordinates, vector region_coordinates, vector look_at ) does not respond to the vector look_at parameter when teleporting within a Region. When teleporting to another region (meaning different from where avatar started), the vector look_at parameter works fine. I submitted a bug report at: https://jira.secondlife.com/browse/BUG-214737 , which is related to an old comment https://jira.secondlife.com/browse/SVC-7987 Others have discussed this in another topic at This is the test code I used in https://jira.secondlife.com/browse/BUG-214737 . /* Step One. Go to Linden public sandbox region named "Sandbox Mirus". Step Two. Place the following code in a default cube and touch it, being sure to accept the permissions request. Step Three. Observe that the Telport within the region named "Sandbox Mirus" __ DOES NOT __ point you to the specified vector look_at direction. Step Four. Pick the cube up and place the cube in the adjacent region named "Sandbox Peritus." Step Five. Once again touch the cube, being sure to accept the permissions request. The script will teleport you back to region named "Sandbox Mirus". Step Six. Observe that your avatar is now indeed pointed in the direction vector look_at direction. */ key agent = NULL_KEY; // Region "Sandbox Mirus" is at global coordinates <256512,130560,0> // A Second Life Premium Sandbox vector global_coordinates = <256512,130560,0>; vector region_coordinates = <128,128,30>; // coordinates relative to region corner // Vector to lookat-direction when landing after teleportation // North is <0., 1., 0.> // South is <0., -1., 0.> // East is <1.,0.,0.> // West is <-1.,0.,0.> // North West is <-1.,1.,0.> // North East is <1.,1.,0.> // South West is <-1.,-1.,0.> // South East is <1.,-1.,0.> vector look_at = <-1.,0.,0.>; // Points West default { state_entry() { agent = llGetOwner(); llRequestPermissions(agent, PERMISSION_TELEPORT); } touch_start(integer total_number) { if ( agent == llDetectedKey(0) ) { llTeleportAgentGlobalCoords( agent, global_coordinates, region_coordinates, look_at ); } } run_time_permissions(integer perm) { // if permission request has been denied (read ! as not) if (!(perm & PERMISSION_TELEPORT)) { llSay(PUBLIC_CHANNEL, "I need Owner permissions to teleport Owner!"); llRequestPermissions(agent, PERMISSION_TELEPORT); } } }
  10. Well, if I thought there would be this many changes I would have posted in LSL Scripting instead of LSL Library. Apologies. Next time I'll start off in LSL scripting. The random dither on the landing point is a good idea. I have added that. The rounding actually only applies to the SIM/Region corner calculation. Logically, or philosophically, the SIM/Region corner is an integer, though the vectors carry it in float values. // Erwin Solo 2018-03-12b V1.0.2 // Experience Based Teleporter // Step 1. Set up an experience on your land. See Linden Article at // https://community.secondlife.com/knowledgebase/english/experiences-in-second-life-r1365/ // Recompile this script to set it to the experience name of your land. Quoting the Linden Article: // "LSL scripts must be specifically compiled for an experience in order to make use of experience-related LSL functions. The bottom of the LSL editor in the Second Life Viewer includes a checkbox for Use Experience and a dropdown for selecting which of your experience keys you wish the script to use." // Step 3: Place one landmark in the teleporter and you are done // Revisions // 2018-03-12 Revision 1.0.2 Introduced random dither to landing location to keep avatars from landing on top of one another // 2018-03-12 Revision 1.0.1 // Added ability to control the direction in which avatar faces when landing: North, South, East, West, North East, North West, South East, South West. // Disabled teleportation until device initialization is complete. // 2018-03-11 Revision 1.0 Initial Release integer giDebug = FALSE; // set to FALSE to quiet local debug messages or to TRUE to display local debug messages // Vector to lookat-direction when landing after teleportation // North is <0., 1., 0.> // South is <0., -1., 0.> // East is <1.,0.,0.> // West is <-1.,0.,0.> // North West is <-1.,1.,0.> // North East is <1.,1.,0.> // South West is <-1.,-1.,0.> // South East is <1.,-1.,0.> vector gvLookat = <0.,1.,0.>; // Populate with Vector to lookat-direction when landing after teleportation // ===== Don't change anything below here =========== vector gvSIM_Global_Coordinates = ZERO_VECTOR; // Global coordinates of your landmark, once finally calculated vector gvLocal_Coordinates = ZERO_VECTOR; // Local coordinates of your landmark on its destination region vector gvTargetSimCorner = ZERO_VECTOR; // Global coordinates for the Region-Corner of your landmark, once finally calculated vector gvRelative_Coordinates = ZERO_VECTOR; // Relative coordinates of your landmark relative to the position of your teleporter vector gvCurrentSimGlobal = ZERO_VECTOR; // Global coordinates for the Region-Corner of the region on which your teleporter resides key gkLocalCoordinateQuery = NULL_KEY; // a handle to be used in a dataserver call string gsLandMarkName = ""; // The name of the landmark in your inventory string gsErrorMessage = ""; // Used to build string for error messages list glDither = [0.5, 0.5, -0.5, -0.5, 0.0, 0.0]; // Dither offset for landing positions so avatars don't land on top of each other list glShuffledList = []; // Global variable for shuffled list default { state_entry() { // Turn off collision detection until calculations are complete llVolumeDetect(FALSE); // Get Global Coordinates of corner of Current SIM on which the teleporter resides gvCurrentSimGlobal =llGetRegionCorner(); //complain if there are no landmarks if (llGetInventoryNumber(INVENTORY_LANDMARK) == 0) { llSay(PUBLIC_CHANNEL, "There are no landmarks in me. You need to put a landmark in me for me to work."); } //complain if there is more than one landmark else if (llGetInventoryNumber(INVENTORY_LANDMARK) > 1) { llSay(PUBLIC_CHANNEL, "There are TOO MANY landmarks in me. You need to put EXACTLY ONE landmark in me for me to work."); } else { // Get name of the single landmark in inventory gsLandMarkName = llGetInventoryName(INVENTORY_LANDMARK, 0); // Dataserver call for local coordinates of landmark gkLocalCoordinateQuery = llRequestInventoryData( gsLandMarkName ); } } on_rez(integer start_param) { llResetScript(); } changed( integer change ) { if(change & (CHANGED_OWNER | CHANGED_REGION | CHANGED_INVENTORY)) { llResetScript(); } } dataserver(key query_id, string data) { if (query_id == gkLocalCoordinateQuery) { gvRelative_Coordinates = (vector)data; gvSIM_Global_Coordinates = gvRelative_Coordinates + gvCurrentSimGlobal; // Perform a bit of vector math and rounding. // Logically, the SIM/Region corner is an integer but must be cast as a float to be in a vector // Math programers may feel the urge to add a small value before rounding, // to prevent erronious down-rounding but that is not necessary // unless the landmark is exactly at the Region's <0.0, 0.0, 0.0> point // and that is an impossible landmark to create inworld because avatars // all have non-zero height. gvTargetSimCorner = < 256.0 * (float) ( (integer) (gvSIM_Global_Coordinates.x / 256.0)), 256.0 * (float) ( (integer) (gvSIM_Global_Coordinates.y / 256.0)), 0.0 >; // Local coordinates are not rounded because global coordinates are not rounded // Only the SIM/Region corner value has been rounded gvLocal_Coordinates = gvSIM_Global_Coordinates - gvTargetSimCorner; if (giDebug) { llSay (PUBLIC_CHANNEL, "gvCurrentSimGlobal:" + (string)gvCurrentSimGlobal); llSay (PUBLIC_CHANNEL, "gvSIM_Global_Coordinates:" + (string) gvSIM_Global_Coordinates); llSay (PUBLIC_CHANNEL, "gvTargetSimCorner:" + (string)gvTargetSimCorner); llSay (PUBLIC_CHANNEL, "gvLocal_Coordinates:" + (string)gvLocal_Coordinates); } // Prepare object to detect collision_start events when interpenetrating. llVolumeDetect(TRUE); } } collision_start(integer detected) { llRequestExperiencePermissions(llDetectedKey(0), ""); // Shuffle dither list while server is checking permissions in parallel glShuffledList = llListRandomize ( glDither, 1) ; // randomize order of offset values, all of which are float type } experience_permissions( key agent_id ) { // teleport to local coordinates within SIM / Region, with random dither offset to local coordinates llTeleportAgentGlobalCoords( agent_id, gvTargetSimCorner, (<gvLocal_Coordinates.x + llList2Float( glShuffledList, 0 ), gvLocal_Coordinates.y + llList2Float( glShuffledList, 1 ), gvLocal_Coordinates.z> ), gvLookat); } experience_permissions_denied( key agent_id, integer reason ) { gsErrorMessage = "Teleport Denied: " + llGetExperienceErrorMessage(reason) + ". "; if (reason == 1) gsErrorMessage += "The call failed due to too many recent calls."; else if (reason == 2) gsErrorMessage += "The region currently has experiences disabled."; else if (reason == 3) gsErrorMessage += "One of the string arguments was too big to fit in the key-value store."; else if (reason == 4) gsErrorMessage += "Experience permissions were denied by the user."; else if (reason == 5) gsErrorMessage += "This script is not associated with an experience."; else if (reason == 6) gsErrorMessage += "The sim was unable to verify the validity of the experience. Retrying after a short wait is advised."; else if (reason == 7) gsErrorMessage += "The script is associated with an experience that no longer exists."; else if (reason == 8) gsErrorMessage += "The experience owner has temporarily disabled the experience."; else if (reason == 9) gsErrorMessage += "The experience has been suspended by Linden Lab customer support."; else if (reason == 10) gsErrorMessage += "An unknown error not covered by any of the other predetermined error states."; else if (reason == 11) gsErrorMessage += "An attempt to write data to the key-value store failed due to the data quota being met."; else if (reason == 12) gsErrorMessage += "The key-value store is currently disabled on this region."; else if (reason == 13) gsErrorMessage += "Unable to communicate with the key-value store."; else if (reason == 14) gsErrorMessage += "The requested key does not exist."; else if (reason == 15) gsErrorMessage += "A checked update failed due to an out of date request."; else if (reason == 16) gsErrorMessage += "The content rating of the experience exceeds that of the region."; else if (reason == 17) gsErrorMessage += "The experience is blocked or not enabled for this land."; else if (reason == 18) gsErrorMessage += "The request for experience permissions was ignored."; llSay(PUBLIC_CHANNEL, gsErrorMessage); llRegionSayTo( agent_id, PUBLIC_CHANNEL, gsErrorMessage ); } }
  11. I used string gsErrorMessage = "Teleport Denied: " + llGetExperienceErrorMessage(reason) + ". "; to get and format the llGetExperienceErrorMessage(reason), and then I used += to add the longer explanation. In particular, I think these are useful to end-users: else if (reason == 4) gsErrorMessage += "Experience permissions were denied by the user."; else if (reason == 8) gsErrorMessage += "The experience owner has temporarily disabled the experience."; else if (reason == 18) gsErrorMessage += "The request for experience permissions was ignored."; Some of the others will be useful to me or other owners/installers.
  12. I completely agree. I scripted two versions. I first scripted a version using llTeleportAgent( key avatar, string landmark, vector position, vector look_at ) , but it was failing about 50% of the time. I couldn't figure out was was wrong, and so I used my other version based on llTeleportAgentGlobalCoords( key agent, vector global_coordinates, vector region_coordinates, vector look_at ). Thanks. This is what I ended up with. // Erwin Solo 2018-03-11 // Experience Based Teleporter // Step 1. Set up an experience on your land. See Linden Article at // https://community.secondlife.com/knowledgebase/english/experiences-in-second-life-r1365/ // Recompile this script to set it to the experience name of your land. Quoting the Linden Article: // "LSL scripts must be specifically compiled for an experience in order to make use of experience-related LSL functions. The bottom of the LSL editor in the Second Life Viewer includes a checkbox for Use Experience and a dropdown for selecting which of your experience keys you wish the script to use." // Step 3: Place one landmark in the teleporter and you are done integer giDebug = FALSE; // set to FALSE to quiet local debug messages or to TRUE to display local debug messages // ===== Don't change anything below here =========== vector gvSIM_Global_Coordinates = ZERO_VECTOR; // Global coordinates of your landmark, once finally calculated vector gvLocal_Coordinates = ZERO_VECTOR; // Local coordinates of your landmark on its destination region vector gvTargetSimCorner = ZERO_VECTOR; // Global coordinates for the Region-Corner of your landmark, once finally calculated vector gvRelative_Coordinates = ZERO_VECTOR; // Relative coordinates of your landmark relative to the position of your teleporter vector gvCurrentSimGlobal = ZERO_VECTOR; // Global coordinates for the Region-Corner of the region on which your teleporter resides key gkLocalCoordinateQuery = NULL_KEY; // a handle to be used in a dataserver call string gsLandMarkName = ""; // The name of the landmark in your inventory string gsErrorMessage = ""; // Used to build string for error messages default { state_entry() { // Prepare object to collision_start events when interpenetrating. llVolumeDetect(TRUE); // Get Global Coordinates of corner of Current SIM on which the teleporter resides gvCurrentSimGlobal =llGetRegionCorner(); //complain if there are no landmarks if (llGetInventoryNumber(INVENTORY_LANDMARK) == 0) { llSay(PUBLIC_CHANNEL, "There are no landmarks in me. You need to put a landmark in me for me to work."); } //complain if there is more than one landmark else if (llGetInventoryNumber(INVENTORY_LANDMARK) > 1) { llSay(PUBLIC_CHANNEL, "There are TOO MANY landmarks in me. You need to put EXACTLY ONE landmark in me for me to work."); } else { // Get name of the single landamrk in inventory gsLandMarkName = llGetInventoryName(INVENTORY_LANDMARK, 0); // Dataserver call for local coordinates of landmark gkLocalCoordinateQuery = llRequestInventoryData( gsLandMarkName ); } } on_rez(integer start_param) { llResetScript(); } changed( integer change ) { if(change & (CHANGED_OWNER | CHANGED_REGION | CHANGED_INVENTORY)) { llResetScript(); } } dataserver(key query_id, string data) { if (query_id == gkLocalCoordinateQuery) { gvRelative_Coordinates = (vector)data; gvSIM_Global_Coordinates = gvRelative_Coordinates + gvCurrentSimGlobal; // Perform a bit of vector math and rounding. // Math programers may feel the urge to add a small value before rounding, // to prevent erronious down-rounding but that is not necessary // unless the landmark is exactly at the Region's <0.0, 0.0, 0.0> point // and that is an impossible landmark to create inworld because avatars // all have non-zero height. gvTargetSimCorner = < 256.0 * (float) ((integer) (gvSIM_Global_Coordinates.x / 256.0)), 256.0 * (float) ((integer) (gvSIM_Global_Coordinates.y / 256.0)), 0.0 >; gvLocal_Coordinates = gvSIM_Global_Coordinates - gvTargetSimCorner; if (giDebug) { llSay (PUBLIC_CHANNEL, "gvCurrentSimGlobal:" + (string)gvCurrentSimGlobal); llSay (PUBLIC_CHANNEL, "gvSIM_Global_Coordinates:" + (string) gvSIM_Global_Coordinates); llSay (PUBLIC_CHANNEL, "gvTargetSimCorner:" + (string)gvTargetSimCorner); llSay (PUBLIC_CHANNEL, "gvLocal_Coordinates:" + (string)gvLocal_Coordinates); } } } collision_start(integer detected) { llRequestExperiencePermissions(llDetectedKey(0), ""); } experience_permissions( key agent_id ) { llTeleportAgentGlobalCoords(agent_id, gvTargetSimCorner, gvLocal_Coordinates, ZERO_VECTOR); } experience_permissions_denied( key agent_id, integer reason ) { gsErrorMessage = "Teleport Denied: " + llGetExperienceErrorMessage(reason) + ". "; if (reason == 1) gsErrorMessage += "The call failed due to too many recent calls."; else if (reason == 2) gsErrorMessage += "The region currently has experiences disabled."; else if (reason == 3) gsErrorMessage += "One of the string arguments was too big to fit in the key-value store."; else if (reason == 4) gsErrorMessage += "Experience permissions were denied by the user."; else if (reason == 5) gsErrorMessage += "This script is not associated with an experience."; else if (reason == 6) gsErrorMessage += "The sim was unable to verify the validity of the experience. Retrying after a short wait is advised."; else if (reason == 7) gsErrorMessage += "The script is associated with an experience that no longer exists."; else if (reason == 8) gsErrorMessage += "The experience owner has temporarily disabled the experience."; else if (reason == 9) gsErrorMessage += "The experience has been suspended by Linden Lab customer support."; else if (reason == 10) gsErrorMessage += "An unknown error not covered by any of the other predetermined error states."; else if (reason == 11) gsErrorMessage += "An attempt to write data to the key-value store failed due to the data quota being met."; else if (reason == 12) gsErrorMessage += "The key-value store is currently disabled on this region."; else if (reason == 13) gsErrorMessage += "Unable to communicate with the key-value store."; else if (reason == 14) gsErrorMessage += "The requested key does not exist."; else if (reason == 15) gsErrorMessage += "A checked update failed due to an out of date request."; else if (reason == 16) gsErrorMessage += "The content rating of the experience exceeds that of the region."; else if (reason == 17) gsErrorMessage += "The experience is blocked or not enabled for this land."; else if (reason == 18) gsErrorMessage += "The request for experience permissions was ignored."; llSay(PUBLIC_CHANNEL, gsErrorMessage); llRegionSayTo( agent_id, PUBLIC_CHANNEL, gsErrorMessage ); } }
  13. Below is my version of an experience based teleporter. It works upon avatar collision with the teleporter. Instead of requiring manual entry of coordinates, it reads the necessary coordinates from a landmark in inventory. Any improvements would be most welcome. Experience Based Teleporter using Landmarks // Erwin Solo 2018-03-11 // Experience Based Teleporter // Step 1. Set up an experience on your land. See Linden Article at // https://community.secondlife.com/knowledgebase/english/experiences-in-second-life-r1365/ // Recompile this script to set it to the experience name of your land. Quoting the Linden Article: // "LSL scripts must be specifically compiled for an experience in order to make use of experience-related LSL functions. The bottom of the LSL editor in the Second Life Viewer includes a checkbox for Use Experience and a dropdown for selecting which of your experience keys you wish the script to use." // Step 3: Place one landmark in the teleporter and you are done // ===== Don't change anything below here =========== vector gvSIM_Global_Coordinates = ZERO_VECTOR; vector gvLocal_Coordinates = ZERO_VECTOR; vector gvTargetSimCorner = ZERO_VECTOR; vector gvRelative_Coordinates = ZERO_VECTOR; vector gvCurrentSimGlobal = ZERO_VECTOR; key gLocalCoordinateQuery = NULL_KEY; string gLandMarkName = ""; default { state_entry() { llVolumeDetect(TRUE); // Get Global Coordinates of Current SIM gvCurrentSimGlobal =llGetRegionCorner(); llSay (0, (string) gvCurrentSimGlobal); //complain if there are no landmarks if (llGetInventoryNumber(INVENTORY_LANDMARK) == 0) { llSay(PUBLIC_CHANNEL, "There are no landmarks in me. You need to put a landmark in me for me to work."); } //complain if there is more than one landmark else if (llGetInventoryNumber(INVENTORY_LANDMARK) > 1) { llSay(PUBLIC_CHANNEL, "There are TOO MANY landmarks in me. You need to put EXACTLY ONE landmark in me for me to work."); } else { // Get name of the single landamrk in inventory gLandMarkName = llGetInventoryName(INVENTORY_LANDMARK, 0); // Dataserver call for local coordinates of landmark gLocalCoordinateQuery = llRequestInventoryData( gLandMarkName ); } } on_rez(integer start_param) { llResetScript(); } changed( integer change ) { if(change & (CHANGED_OWNER | CHANGED_REGION | CHANGED_INVENTORY)) { llResetScript(); } } dataserver(key query_id, string data) { if (query_id == gLocalCoordinateQuery) { gvRelative_Coordinates = (vector)data; gvSIM_Global_Coordinates = gvRelative_Coordinates + gvCurrentSimGlobal; // Perform a bit of vector math and rounding gvTargetSimCorner = < 256.0 * (float) ((integer) (gvSIM_Global_Coordinates.x / 256.0)), 256.0 * (float) ((integer) (gvSIM_Global_Coordinates.y / 256.0)), 0.0 >; gvLocal_Coordinates = gvSIM_Global_Coordinates - gvTargetSimCorner; // llOwnerSay ("gvSIM_Global_Coordinates:" + (string) gvSIM_Global_Coordinates); // llOwnerSay ("gvTargetSimCorner:" + (string)gvTargetSimCorner); // llOwnerSay ("gvLocal_Coordinates:" + (string)gvLocal_Coordinates); } } collision_start(integer detected) { llRequestExperiencePermissions(llDetectedKey(0), ""); llSay(0, "You need to accept the Experience Permission Request for this to work."); } experience_permissions( key agent_id ) { llTeleportAgentGlobalCoords(agent_id, gvTargetSimCorner, gvLocal_Coordinates, ZERO_VECTOR); } experience_permissions_denied( key agent_id, integer reason ) { llSay(0, "Denied: " + llGetExperienceErrorMessage(reason) + ". You need to accept the Experience Permission Request for this to work."); } }
  14. Well, that would help if the only application were sword tournaments. What about the full-sim races for vehicles?
  15. Whirly, thanks. The Estate/Region tools using Disable Selected" is useful because it lets me disable other people scripts, but the capability isn't all that useful unless I can reverse the process.
  16. Refer to http://wiki.secondlife.com/wiki/Viewerhelp:Top_Colliders_and_Top_Scripts for context. Also http://wiki.secondlife.com/wiki/Estate_Menu . When I disable a script via the Estate/Region tools using Disable Selected" in "Get Top Scripts" on the Region/Estate (Alt-R) Debug Tab, is there a way to re-enable them? Currently, I only disable scripts this way when I am willing to put down a new copy of the item to get the functionality back (e.g., scripted trees with a season-changing script). I have events in my Region like Sword Tournaments, during which I would like to turn off all scripts except those of contestants and scoreboard. But, I unless I can turn back-on the scripts I've turned off, this aspect of the Region/Estate tools won't help me much.
  17. Greetings, Background: I did a fair amount of Blender creation in 2013 and 2014 and just kind of quit. I noticed the opportunity to get a one-year Maya LT license for not too much money, and so I am trying that. I see two ways to convert Maya LT files to dae files for upload to Second Life: (1) Autodesk FBX Converter, and (2) Export from Maya to obj files and the import to Blender and then export from Blender to dae files. Question: What is the best way for me to convert from Maya LT to dae files for import into SL? My main interest is in architectural items. I have no interest in making clothing or mesh avatars. My priorities are more on time-savings rather than L$ savings. I do use the Aditi grid if I'm doing a big project, to cut down on the upload fees. When I upload to the main grid, it would be nice if the textures import into SL just like I see them in Maya. If I end up paying for an extra L$10 texture upload or two every once in a while, that's not going to break the bank. I do this for fun not to make L$. Oh, and I'd like to make some mesh "ground" for my skybox applications, and I might want to make an organic shape now and then. Is Mudbox a good tool for me, since I'm already invested in the Autodesk family with Maya?
  18. Gorean Themed Rentals L$1 per prim per week. SURL: http://maps.secondlife.com/secondlife/Jaraded/108/206/59
  19. The buyer does not know what the tier date is. The seller knows, but the buyer not so much. https://community.secondlife.com/t5/Land/If-I-buy-a-full-region-for-the-US-600-set-up-fee-does-the-600/qaq-p/3026386
  20. The posters above told you what you need to know. The silly answer is that the smallest lot size on a Region is 4x4 = 16 square meters. You can, therefore, have 256x256 / 16 = 4096 individual plots on a Region each large enough to stand on. But, as already explained, the Regions limit on the number of avatars is what really matters.
×
×
  • Create New...