CLASS 49: Auto-Return and Rental Scripts
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:
- Design and script a fully automated rental payment system.
- Utilize
timerevents to create a script "heartbeat" for checking rent status. - Master
llSetPrimitiveParamsto provide visual feedback on rental status (e.g., changing color and text). - Use
llGetObjectDetailsto identify and manage objects owned by a specific tenant. - Implement a robust auto-return feature to reclaim unpaid rental space automatically.
- Send automated rent reminders and confirmation messages to tenants for a professional user experience.
- Structure your script using states for clean, efficient, and easy-to-debug code.
Prerequisites
This is an Advanced scripting class. To succeed, you should be comfortable with the following LSL concepts:
- LSL Fundamentals: Variables (integers, floats, strings, keys, lists), operators, and control flow (if/else statements).
- Events: A solid understanding of events like
state_entry(),touch_start(), andmoney(). - States: You must know how to declare and switch between different states in a script.
- Permissions: Basic knowledge of how to request permissions from the owner using
llRequestPermissions(). - Viewer Build Tools: You should know how to create a prim, place a script inside it, and edit its properties in-world using a viewer like Firestorm.
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.
default: The initial state. It handles setup and permissions, then immediately transitions to the `Available` state.Available: The state when the rental unit is vacant and ready to be rented.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 usellGetUnixTime()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 likellSensor()andllGetObjectDetails()can be very heavy on server resources if used improperly. Never put them inside a very fasttimer()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:
- Configuration Notecard: Instead of hardcoding variables like
gRentPrice, read them from a notecard usingllGetNotecardLine. This allows you or other managers to change rental settings without editing the script. - Tiered Pricing: Modify the
money()event to accept different payment amounts for different rental durations (e.g., pay more for a 30-day rental). - Web Integration: Use
llHTTPRequestto log rental data to an external website or database, allowing you to manage your entire rental empire from a web dashboard. - Group-Based Rentals: Check if a paying user is a member of a specific group before allowing them to rent, creating exclusive residential areas.
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:
- When the rent is first overdue, the box should turn red and display a "GRACE PERIOD" message.
- The script should send an "urgent" overdue notice to the tenant.
- The objects should only be returned if the grace period (24 hours after the original due date) has also passed.
- If the tenant pays during the grace period, the rent should be considered renewed from the original due date, not the payment date.
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_DEBITwas 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 therun_time_permissionsrequest. 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
3600seconds (one hour) is very server-friendly. Avoid setting timers to less than 60 seconds. Also, keep thegScanRadiusas small as is practical for the rental area. UsingllReturnObjectsByOwneris 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
llInviteToGroupto invite them to the group, giving them build rights. When their rent expires, the script would usellEjectFromGroupto 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.
🎓 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