User:Daemonika Nightfire/Scripts/Building Rezzer

From Second Life Wiki
Jump to navigation Jump to search

*DS* Building Rezzer 2024

You need both scripts, the rezzer script is for your rezzer, the client script is for the objects you want to rezz.

*DS* Building Rezzer v2024.0.02

/*
    *DS* Building Rezzer 2024 by Daemonika Nightfire
    
    This rezzer is my interpretation of a building rezzer.
    With this tool you can manage structures region-wide.
    
    
    ➤ Setup
    Place the '*DS* Building Rezzer' script in a desired object that is to represent your rezzer.
    The second script '*DS* Building Client' is intended for the root content of your buildings.
    
    Once all your buildings have a script, click on the rezzer and select the [record] button in the menu.
    All objects will report back to you, then take all objects into your inventory and transfer them to the contents of your rezzer.
    
    It is not absolutely necessary to give all objects an individual name.
    Individual names are only of interest to you so that they are not numbered in the Rezzer.
    
    ➤ Rezzing
    Of course, all objects are rezzed at the same position, but are then moved to the valid position/rotation by the client script.
    If you then move or rotate the rezzer, the objects with the client script follow after 1 second.
    
    
    You can find updates here: https://wiki.secondlife.com/wiki/User:Daemonika_Nightfire/Scripts/Building_Rezzer
*/

key owner;

//////////////////////////////////////// Communication \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

// Any channel is possible. (is automatically transmitted to the clients)
integer com_channel = -123456;

// Must be the same in the client script.
integer record_channel = -123456789;
float seconds = 1.0;

string menu_desc = "\n[record] the clients save the coordinates\n[rez] your building is rezzed\n[derez] will delete your building\n[del. scripts] removes the scripts from the clients\n[reset] resetting me\n";
integer menu_status = 0;
integer menu_countdown = 60;
integer menu_handler;
integer menu_channel;
integer dynamic_channel()
{
    menu_status = 1;
    menu_countdown = 60;
    llListenRemove(menu_handler);
    
    menu_channel = (integer)(llFrand(1) * -DEBUG_CHANNEL);
    menu_handler = llListen(menu_channel,"","","");
    
    return menu_channel;
}

//////////////////////////////////////// Rezzer \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

// Coordinates where the objects are to be rezzed (not the final place).
vector Position = <0.0, 0.5, 0.5>;
vector Rotation = <0.0, 0.0, 0.0>;

list content = [];
integer items;
Rezzer()
{
    integer i = 0;
    do
    {
        vector BasePos = llGetPos();
        rotation BaseRot = llGetRot();
        rotation quat = llEuler2Rot(Rotation * DEG_TO_RAD);
        llRezObjectWithParams(llList2String(content, i), [REZ_PARAM, com_channel,
                                                          REZ_POS, BasePos + (Position * BaseRot), FALSE, TRUE,
                                                          REZ_ROT, quat * BaseRot, FALSE]);
    }
    while(++i < items);
    
    // After all objects have been rezzed, the command to move to the final place is triggered.
    llRegionSay(com_channel, "move|" + coordinates());
}

//////////////////////////////////////// Coordinates \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

string stored_message;
string coordinates()
{
    vector pos = llGetPos();
    rotation rot = llGetRot();
    return (string)pos + "|" + (string)rot;
}

default
{
    state_entry()
    {
        owner = llGetOwner();
        stored_message = coordinates();
        
        items = llGetInventoryNumber(INVENTORY_OBJECT);
        if(items > 0)
        {
            integer i = 0;
            do
            {
                content += llGetInventoryName(INVENTORY_OBJECT, i);
            }
            while(++i < items);
        }
        
        llSetText("Items loaded " + (string)items, <1,1,1>, 1.0);
        llRegionSayTo(owner, 0, "/me - " + llGetScriptName() + " Memory: " + (string)llGetUsedMemory() + " bytes in use.");
        
        llSetTimerEvent(1);
    }
    
    touch_start(integer total_number)
    {
        key agent = llDetectedKey(0);
        if(agent == owner)
        {
            llDialog(agent, menu_desc, ["del. scripts","reset","close","record","rez","derez"], dynamic_channel());
        }
    }
    
    listen(integer chan, string name, key id, string msg)
    {
        if(chan == menu_channel)
        {
            if(msg == "close")
            {
                menu_status = 0;
                menu_countdown = 0;
                llListenRemove(menu_handler);
                return;
            }
            else if(msg == "del. scripts")
            {
                llRegionSay(com_channel, "remove_scripts");
            }
            else if(msg == "derez")
            {
                llRegionSay(com_channel, "delete");
            }
            else if(msg == "rez")
            {
                // Prevents multiple objects at the same place.
                llRegionSay(com_channel, "delete");
                
                // Rezzing is only triggered if there are objects in the content.
                if(items > 0)
                {
                    Rezzer();
                }
            }
            else if(msg == "record")
            {
                llRegionSay(record_channel, "record|" + coordinates());
            }
            else if(msg == "reset")
            {
                llResetScript();
            }
            llDialog(id, menu_desc, ["del. scripts","reset","close","record","rez","derez"], dynamic_channel());
        }
    }

    timer()
    {
        if(menu_status)
        {
            menu_countdown--;
            if(menu_countdown == 0)
            {
                menu_status = 0;
                menu_countdown = 60;
                llListenRemove(menu_handler);
            }
        }
        
        // If the rezzer is moved, the coordinates no longer match.
        if(stored_message != coordinates())
        {
            // In this case, the move command is triggered again.
            llRegionSay(com_channel, "move|" + coordinates());
            stored_message = coordinates();
        }
    }
    
    changed(integer ch)
    {
        if(ch & CHANGED_INVENTORY)
        {
            llResetScript();
        }
    }
    
    on_rez(integer Dae)
    {
        llResetScript();
    }
}

*DS* Building Client v2024.0.02

key owner;

// automatically received by the rezzer
integer com_channel = -1978; // dummy channel (do not change)

// Must be the same in the rezzer script.
integer record_channel = -123456789;
integer channel_handler; 

vector relative_position;
rotation relative_rotation;

default
{
    state_entry()
    {
        owner = llGetOwner();
        channel_handler = llListen(record_channel, "", "", "");
    }
    
    listen(integer chan, string name, key id, string msg)
    {
        // Prevents interference from other objects in the same channel.
        if(llGetOwnerKey(id) == owner)
        {
            list temp = llParseString2List(msg, ["|"], []);
            string cmd = llList2String(temp, 0);
            vector rezzer_pos = (vector)llList2String(temp, 1);
            rotation rezzer_rot = (rotation)llList2String(temp, 2);
                
            if(chan == record_channel)
            {
                if(cmd == "record")
                {
                    relative_position = (llGetPos() - rezzer_pos) / rezzer_rot;
                    relative_rotation = llGetRot() / rezzer_rot;
                    llRegionSayTo(owner, 0, "stored: " + (string)relative_position + " | " + (string)relative_rotation);
                }
            }
            else if(chan == com_channel)
            {
                // Prevents other rezzers of the same owner from interfering.
                list details = llGetObjectDetails(llGetKey(), [OBJECT_REZZER_KEY]);
                key rezzer = llList2Key(details, 0);
                if(rezzer == id)
                {
                    if(cmd == "move")
                    {
                        vector dest = rezzer_pos + (relative_position * rezzer_rot);
                        float ground = llGround(dest);
                        
                        // Make sure that the target coordinates are within the region.
                        if(dest.x > 0 && dest.x < 256 && dest.y > 0 && dest.y < 256 && dest.z > ground && dest.z < 4096)
                        {
                            llSetRegionPos(dest); // Move imediately to the target coordinates.
                        }
                        else
                        {
                            llRegionSayTo(owner, 0, "\nImpossible position, destination would be outside possible coordinates of this region.\nPlease move the rezzer back a little or change the altitude.");
                        }
                        llSetRot(relative_rotation * rezzer_rot);
                    }
                    else if(cmd == "delete")
                    {
                        llDie();
                    }
                    else if(cmd == "remove_scripts")
                    {
                        llRemoveInventory(llGetScriptName());
                    }
                }
            }
        }
    }
    
    on_rez(integer Dae)
    {
        owner = llGetOwner();
        llListenRemove(channel_handler);
        
        // Overwrites the dummy channel with the one from the rezzer.
        com_channel = Dae;
        llListen(com_channel, "", "", "");
    }
}