HELP
Scripting Advanced Published: 2026-03-27  |  ← Back to School

CLASS 49: Auto-Return and Rental Scripts

Auto-Return and Rental Scripts — Alife Virtual School

Auto-Return and Rental Scripts — Free class in Alife Virtual School

Welcome, creators and entrepreneurs of the metaverse! In the sprawling, dynamic digital landscape of Alife Virtual, the ability to build is only half the equation. The other half is creating systems that bring your world to life and generate value. This advanced scripting class will equip you with one of the most powerful skills for any landowner or business owner: creating Auto-Return and Rental Scripts. Mastering this will allow you to automate your rental properties, manage tenants effortlessly, and build a sustainable income stream within Alife Virtual's burgeoning virtual economy. Forget manual rent collection and messy spreadsheets; it's time to make your scripts do the work for you, creating a truly passive income source in a leading second life alternative.

The Alife Advantage: Building Your Empire for Free

In other virtual worlds, the dream of running a rental business is often crushed by immense upfront costs and recurring monthly fees. A single full region can cost hundreds of dollars per month, and every texture or mesh you upload chips away at your budget. This creates a high barrier to entry, reserving land ownership and large-scale enterprise for a select few.

Alife Virtual shatters that barrier. We believe creativity shouldn't come with a price tag. Here, the tools for building a virtual empire are free, creating a level playing field for everyone. Let's compare the real cost of starting a rental business:

Feature / Cost Alife Virtual Competitors (e.g., Second Life)
Private Island (65,536 sqm) $0 / month. Forever. ~$300 USD / month
Asset Uploads (Mesh, Textures) FREE & Unlimited L$10 (~$0.04) per upload
Script Compilation & Execution FREE Included in tier fees
Cost to Start a Rental Business $0. Your only investment is your time and creativity. Thousands of dollars per year, just for land fees.

This isn't just a minor difference; it's a paradigm shift. In Alife Virtual, you can build a sprawling commercial district, a cozy residential village, or a futuristic skybox metropolis on your FREE private island without spending a dime. The advanced LSL scripting skills you learn today are directly applicable to building a profitable, scalable business in our 100% free economy.

What You Will Learn in This Class

Upon completing this master-level workshop, you will be able to:

Prerequisites

This is an Advanced scripting class. To succeed, you should be comfortable with the following LSL concepts:

Step-by-Step Tutorial: Building Your First Automated Rental Box

We will now build a rental box from the ground up. This object, when touched, will offer to rent the space for a set duration. It will manage the payment, track the due date, and automatically return the tenant's objects if the rent is not renewed. Create a new script in a prim and follow along.

Part 1: The Foundation - Global Variables and States

First, we need to define the core parameters of our rental system and set up our state machine. A state machine allows our script to behave differently depending on its current situation (e.g., `AVAILABLE` vs. `RENTED`).

Add the following global variables to the top of your script. These will act as our configuration settings.

// --- CONFIGURATION ---
integer gRentPrice = 100; // Price per rental period
integer gRentDuration = 604800; // Duration in seconds (7 days)
float gScanRadius = 30.0; // Radius in meters to scan for tenant's objects
string gObjectName = "Rental Box"; // Name for prim text
string gCurrencySymbol = "A$"; // Your virtual currency symbol

// --- SYSTEM VARIABLES ---
key gTenantKey; // Stores the UUID of the current tenant
integer gDueDate; // Stores the Unix timestamp of when the rent is due
key gOwnerKey; // Stores the script owner's key for security
integer gTimerInterval = 3600; // How often to check status (in seconds, 1 hour)

Now, let's define our states. Our script will have three primary modes of operation.

  1. default: The initial state. It handles setup and permissions, then immediately transitions to the `Available` state.
  2. Available: The state when the rental unit is vacant and ready to be rented.
  3. Rented: The state when a tenant has paid and is occupying the space.

Part 2: The 'Default' State - Initialization and Permissions

The default state is our starting point. Its main job is to get the owner's key, request the necessary permissions to accept money, and then switch to the `Available` state to await a tenant.

default
{
    state_entry()
    {
        gOwnerKey = llGetOwner();
        llRequestPermissions(gOwnerKey, PERMISSION_DEBIT);
    }

    run_time_permissions(integer permissions)
    {
        if (permissions & PERMISSION_DEBIT)
        {
            llSay(0, "Permissions granted. System is now active.");
            state Available; // Move to the available state
        }
        else
        {
            llSay(0, "PERMISSION_DEBIT is required for this script to function. Please grant permission.");
        }
    }
    
    // Failsafe: if the script is reset, go back to available
    on_rez(integer start_param)
    {
        llResetScript();
    }
}

Part 3: The 'Available' State - Attracting a Tenant

In the Available state, the rental box needs to display that it's open for business and handle what happens when a user pays it.

state Available
{
    state_entry()
    {
        // Update the prim text and color to show it's available
        llSetText(gObjectName + "\nAvailable\n" + gCurrencySymbol + (string)gRentPrice + " / Week", <0.0, 1.0, 0.0>, 1.0);
        llSetPayPrice(PAY_PRICE_DEFAULT, [gRentPrice]); // Set the price
    }

    money(key id, integer amount)
    {
        if (amount == gRentPrice)
        {
            // Payment received!
            gTenantKey = id; // Store the payer's key
            gDueDate = llGetUnixTime() + gRentDuration; // Calculate the due date
            
            // Thank the new tenant
            llInstantMessage(gTenantKey, "Thank you for your payment! Your rental is valid until " + llGetTimestamp(gDueDate) + ".");
            
            // Inform the owner
            llInstantMessage(gOwnerKey, "Rental unit has been rented by " + llKey2Name(gTenantKey) + ".");
            
            state Rented; // Switch to the Rented state
        }
        else
        {
            // Incorrect payment amount
            llInstantMessage(id, "Incorrect payment amount. The rent is " + gCurrencySymbol + (string)gRentPrice + ". Refunding your payment.");
            llGiveMoney(id, amount);
        }
    }
    
    // If the owner touches it, reset the script (useful for debugging)
    touch_start(integer total_number)
    {
        if (llDetectedKey(0) == gOwnerKey)
        {
            llSay(0, "Resetting script.");
            llResetScript();
        }
    }
}

Pro Tip: Use llGetUnixTime() for Time Tracking
Always use llGetUnixTime() for time-based calculations. It returns the number of seconds since the Unix Epoch (Jan 1, 1970) and is independent of time zones or daylight saving. This ensures your due dates are absolute and accurate across the entire grid.

Part 4: The 'Rented' State - The Automated Management Core

This is where the magic happens. In the Rented state, a timer will periodically check if the rent is overdue. If it is, the script will initiate the auto-return process. It also handles rent renewals.

state Rented
{
    state_entry()
    {
        // Set a timer to check the rent status periodically
        llSetTimerEvent(gTimerInterval);
        
        // Update the prim text to show rented status
        string dueDateStr = llGetTimestamp(gDueDate);
        string tenantName = llKey2Name(gTenantKey);
        llSetText(gObjectName + "\nRENTED by:\n" + tenantName + "\nDue: " + dueDateStr, <1.0, 0.5, 0.0>, 1.0);
    }

    timer()
    {
        integer currentTime = llGetUnixTime();
        integer timeRemaining = gDueDate - currentTime;

        if (currentTime > gDueDate)
        {
            // RENT IS OVERDUE!
            llInstantMessage(gTenantKey, "Your rent is overdue. Your objects will be returned shortly. Please contact the owner if you wish to rent again.");
            llInstantMessage(gOwnerKey, "Rent overdue for tenant " + llKey2Name(gTenantKey) + ". Initiating auto-return.");
            
            // Change color to red to indicate overdue status
            llSetText("RENT OVERDUE\nReturning Objects...", <1.0, 0.0, 0.0>, 1.0);
            
            // Begin the return process
            ReturnTenantObjects();
            
            // Reset for the next tenant
            state Available;
        }
        else if (timeRemaining < 86400 && timeRemaining > 0) // Less than 1 day remaining
        {
            // Send a friendly reminder 24 hours before expiry
            llInstantMessage(gTenantKey, "Friendly reminder: Your rental is due for renewal within 24 hours. To renew, simply pay the rental box again.");
        }
    }

    money(key id, integer amount)
    {
        // Handle rent renewal
        if (id == gTenantKey && amount == gRentPrice)
        {
            gDueDate += gRentDuration; // Extend the due date
            llInstantMessage(gTenantKey, "Thank you for renewing your rent! Your new due date is " + llGetTimestamp(gDueDate) + ".");
            
            // Update the display text again
            state_entry();
        }
        else
        {
            // Someone else tried to pay, or wrong amount
            llInstantMessage(id, "This unit is currently rented. Your payment is being refunded.");
            llGiveMoney(id, amount);
        }
    }
    
    touch_start(integer total_number)
    {
        // Allow the owner to manually trigger the return process
        if (llDetectedKey(0) == gOwnerKey)
        {
            llDialog(gOwnerKey, "Owner Menu: Do you want to forcibly evict this tenant?", ["Evict", "Cancel"], -1);
        }
    }
    
    listen(integer channel, string name, key id, string message)
    {
        if (channel == -1 && message == "Evict")
        {
            llInstantMessage(gOwnerKey, "Forcing eviction as per owner's request.");
            gDueDate = 0; // Set due date to the past to trigger return on next timer event
            timer(); // Manually call the timer function to expedite
        }
    }

    state_exit()
    {
        // Clean up by turning off the timer when leaving this state
        llSetTimerEvent(0);
    }
}

Part 5: The Final Piece - Returning Objects

The ReturnTenantObjects() function is a custom function we will create. It uses the powerful llGetObjectDetails function to scan for objects owned by the overdue tenant and then returns them.

Add this function outside of any state, usually at the very end of the script.

// --- CUSTOM FUNCTIONS ---

ReturnTenantObjects()
{
    // Important: llGetObjectDetails can be resource-intensive.
    // We are scanning for prims owned by the tenant within our defined radius.
    list objectDetails = llGetObjectDetails(gTenantKey, [OBJECT_POS, OBJECT_FLAGS], gScanRadius);
    
    integer i;
    integer count = llGetListLength(objectDetails);
    
    // We create a list of keys to return, as llReturnObjectsByID is more efficient
    list objectsToReturn;
    
    for (i = 0; i < count; i += 2)
    {
        // The list is flattened: [pos1, flags1, pos2, flags2, ...]
        // We don't need the position here, but we must account for it in the list stride.
        
        // We need the object's key. Unfortunately, llGetObjectDetails does not return it directly.
        // A more advanced script might use llSensor, but for this class, we will use a different method
        // for demonstration: llReturnObjectsByOwner. This is simpler but less precise if you have multiple tenants.
        // For a single rental unit, this is often sufficient.
    }
    
    // A simpler and often more direct approach for parcel-based rentals:
    // This command will return ALL objects on the parcel owned by the tenant.
    // It requires the script owner to also own the parcel.
    llReturnObjectsByOwner(gTenantKey, TRUE);

    llInstantMessage(gOwnerKey, "Auto-return command executed for tenant " + llKey2Name(gTenantKey) + ".");
}

Common Mistake: Lag-Inducing Scans
Functions like llSensor() and llGetObjectDetails() can be very heavy on server resources if used improperly. Never put them inside a very fast timer() event (e.g., every second). Our one-hour timer is a safe interval. For high-traffic areas, consider increasing the interval or using more efficient methods like designated rezzing zones.

The use of llReturnObjectsByOwner is a powerful shortcut if your rental box is managing an entire parcel that you own. It's clean, efficient, and requires less complex scripting than iterating through object lists. For this advanced tutorial, it's the recommended method for simplicity and power.

Advanced Applications & Further Learning

This script is a solid foundation. You can expand upon it in numerous ways:

Practice Exercise: The Grace Period

Your task is to modify the script to provide a 24-hour "grace period" after the rent is due.
Requirements:

  1. When the rent is first overdue, the box should turn red and display a "GRACE PERIOD" message.
  2. The script should send an "urgent" overdue notice to the tenant.
  3. The objects should only be returned if the grace period (24 hours after the original due date) has also passed.
  4. If the tenant pays during the grace period, the rent should be considered renewed from the original due date, not the payment date.
This will test your ability to manipulate time-based logic and add another layer of complexity to the state management.

Frequently Asked Questions (FAQ)

1. Why does my script say "Script trying to take money but has not been granted permission"?
This means the PERMISSION_DEBIT was not successfully granted. This can happen if you deny the permission dialog or if the script is reset by someone other than the owner. To fix it, take the script into your inventory and drag it back into the prim. This will re-trigger the run_time_permissions request. You must click "Yes" or "Grant".
2. Can this one script manage an entire apartment building?
Not in its current form. This script is designed for a single rental unit (a shop, a skybox, a parcel). To manage a whole building, you would place a copy of this script in a rental box for each apartment. You could then create a "master" controller that communicates with all the individual rental boxes, but that is a significantly more advanced project.
3. How do I prevent these scripts from causing lag on my free private island?
The biggest cause of lag from rental scripts is an overly aggressive timer or scan radius. Our timer of 3600 seconds (one hour) is very server-friendly. Avoid setting timers to less than 60 seconds. Also, keep the gScanRadius as small as is practical for the rental area. Using llReturnObjectsByOwner is also highly efficient as it's a native grid function.
4. Can I use this script to rent out the land itself, not just a skybox?
Absolutely. The script acts as the payment and management interface. To rent out a parcel of land, you would deed the land to a group that you control, and set the land to only allow building for that group. When a tenant pays your rental box, your script can use llInviteToGroup to invite them to the group, giving them build rights. When their rent expires, the script would use llEjectFromGroup to remove them.

Start Your Virtual Enterprise in Alife Virtual Today!

You now possess the knowledge to create sophisticated, automated systems that are the bedrock of a successful virtual business. In a world like Alife Virtual, where the financial barriers to entry have been completely removed, your potential is limited only by your imagination and skill.

Why wait? Claim your FREE 65,536 sqm private island, enjoy FREE unlimited uploads for all your creations, and start building your dream with our free pro mesh avatar. Experience the creative freedom of a true free 3D world, fully compatible with the Firestorm viewer you already know and love.

Join Alife Virtual today and turn your scripting skills into a thriving business in the metaverse's most creator-friendly economy!


🎓 Ready to Practice In-World?

Get your FREE island and practice everything you just learned — no credit card, no monthly fees.

Claim Your Free Island Now →

No credit card required · Takes 2 minutes · Your island is FREE forever


Published: 2026-03-27 · Difficulty: Advanced · Category: Scripting  |  Questions? Contact us  |  ← Back to School