NWN2Wiki
Advertisement


randominterior and exitrandomtp

What it does

This pair of scripts takes players to randomly selected interiors when using doors and returns them back to their original location when they leave the interior space.


Description

UPDATED TO VERSION 2.0 Here is a little script I put together to use for big cities where every building has some random filler content that isn't plot or important, but is filled in with encounters.

Here is what you need to do

  • Make 1-20 interior areas generically, and fill with items, encounters, etc.
  • Place a waypoint in each one with the TAG WP_RandomX where X = 1 to 20 (actually the tag format is not required, but you'll need to specify the right tag in the script.)
  • On the door out, attach the exitrandomtp script to the OnAreaTransitionClick or OnOpen event.
  • Now for each door in the outer area you create, attach the randominterior script to the OnAreaTransitionClick or OnOpen event.

This should take the party to a randomly selected interior let them fight, loot, etc, then take them back to the starting point when they use the door to get out. Once they leave the treasure will delay then respawn, encounters in the interiors will respawn at intervals set on the encounter.

I suggest setting the encounter respawns to a minimum of 7 minutes and maximum of 15 minutes, depending on how close together the doors are. This is subject to your own testing based on the size of the areas you build for the interiors. The treasure respawn is set to 45 seconds after exiting, but this is adjustable to your needs.


Notes

New in 1.5: Now henchmen, familiars, summoned, etc will come with you into the rooms. Treasure respawning code added to repopulate placeables that can contain loot. New in 2.0: Made code usable on persistent and multiparty worlds. Set random chance to lock chests on treasure respawn.

Future Improvements Pending: Set random chance to lock door on exit of last member Use random doors unless character has a city map, then all doors stay static once visited.


Side Effects

Some side effects of this script are present, not sure I know how to avoid them at this point. First, the same door may take you to different interiors when revisting the door. Also if the party splits up and clicks multiple doors, they will end up in the same place. Not good for Hard Core RP Rules or "reality" in the game.


Module Level variables used

iPartyCount - Used to track how many go in so you can get them all back out and reset at the end. sRandomTPActive - Flag for determining if a current random Teleport is going on so all party members can be sent to the same location and holds group leader name.


User Level Variables

lRandomTPLoc - The loc a user teleported from so they can be returned to that location later.


The Scripts

/*//////////////////////////////////////////////
// Random Generic Interior Script v2.1
////////////////////////////////////////////////
// This script rolls 1dX set the door to the random interior determined by the roll.
//  All ensuing clicks for the party go to same location until entire party leaves.
//  X can be values 2, 3, 4, 6, 8, 10, 12, or 20
////////////////////////////////////////////////
// Script by Jordinn, shea@oz.net
// Date Created: v1.0 7/16/02, v1.5 7/21/02, v2.0 8/28/02, v2.1 9/6/02
////////////////////////////////////////////////
// props to Lenkyl Greatstorm for the random speech script that I based this on and
//  Malachai Moonshadow and Raasta for the code or clues they provided
//  and Drainc for the feedback provided
//////////////////////////////////////////////*/
/*//////////////////////////////////////////////
// Notes on Script v2.1:
//  May need to implement scripts to enforce group cohesion on door use
// Introduces some nonhardcore RP issues:
//  Same door can go to multiple places when revisted.
//  Split party clicking multiple doors go to same place, but return to original loc on exit
////////////////////////////////////////////////
// Variable Notes:
// On oUser, for storing the location you came from
//  location lRandomTPLoc;
// On oUser, the flag for Active Teleport, "GroupLeaderNN" (N= 00[inactive] or 01-20[active])
//  string sRandomTPActive;
// On oUser, counts party to know when to reset sRandomTPActive, stores on all party
//  int iPartyCount;
//////////////////////////////////////////////*/
string ParseData(string sDataString, string sFlag)
{
    string sReturnVal;
    // This function parses the name and number stored in oUser
    // Data format expected STRINGnn
    if ((sDataString == "") || (sFlag == ""))
    {
        sReturnVal = "ERROR INVALID PARAMETERS";
    }
    else
    {
        if (sFlag == "i")
        {
            sReturnVal = GetStringRight(sDataString, 2);
        }
        else if (sFlag == "s")
        {
            sReturnVal = GetStringLeft(sDataString, (GetStringLength(sDataString)-2));
        }
        else
        {
            sReturnVal = "ERROR BAD FLAG";
        }
    }
    return sReturnVal;
}
void main()
{
    ////////////////////////////////////////////////
    // Specify the waypoint names for later use.
    //  Change WP_RandomX to correct waypoints built into the target areas.
    // Comment out the lines not used.
    ////////////////////////////////////////////////
    string sWaypoint1 = "WP_Random1";
    string sWaypoint2 = "WP_Random2";
    string sWaypoint3 = "WP_Random3";
    string sWaypoint4 = "WP_Random4";
    string sWaypoint5 = "WP_Random5";
    string sWaypoint6 = "WP_Random6";
    /*string sWaypoint7 = "WP_Random7";
    string sWaypoint8 = "WP_Random8";
    string sWaypoint9 = "WP_Random9";
    string sWaypoint10 = "WP_Random10";
    string sWaypoint11 = "WP_Random11";
    string sWaypoint12 = "WP_Random12";
    string sWaypoint13 = "WP_Random13";
    string sWaypoint14 = "WP_Random14";
    string sWaypoint15 = "WP_Random15";
    string sWaypoint16 = "WP_Random16";
    string sWaypoint17 = "WP_Random17";
    string sWaypoint18 = "WP_Random18";
    string sWaypoint19 = "WP_Random19";
    string sWaypoint20 = "WP_Random20";*/
    //  Declare object and set to what clicked on the door or area transition
    object oUser = GetClickingObject();
    //  Change to below if using enter instead of click as event to fire transition
    // object oUser = GetEnteringObject();
    //  If somehow this is done via conversation, try using this line
    // object oUser = GetPCSpeaker();
    // Declare an object to hold GroupLeader
    object oLeader;
    string sGoupLeader;
    // Declare string to hold data during build and parse functions
    string sDataString;
    // Declare object for target of teleport
    object oTarget;
    // Declare int for random number use
    int iRolledNum;
    // Declare variable to store temp count data
    int iTempCount;
    // Declare for use setting variable on party members
    object oParty;
    // Get the Party Leader or PC Name to use in variable
    oLeader = GetFactionLeader(oUser);
    if (!(GetIsObjectValid(oLeader)))
    {
        sGroupLeader = GetName(oUser);
    }
    else
    {
        sGroupLeader = GetName(oLeader);
    }
    // Defines the random number rolled.  Comment out the lines not used.
    // Avoid rerolling if we've got an active TP going.
    if (GetLocalString(oUser, "sRandomTPActive") == "")
    {
        // iRolledNum = d2(1);
        // iRolledNum = d3(1);
        // iRolledNum = d4(1);
        iRolledNum = d6(1);
        // iRolledNum = d8(1);
        // iRolledNum = d10(1);
        // iRolledNum = d12(1);
        // iRolledNum = d20(1);
    }
    else
    {
        // If active TP going on, use the existing number stored
        sDataString = GetLocalString(oUser, "sRandomTPActive");
        iRolledNum = StringToInt(ParseData(sDataString, "i"));
    }
    if(iRolledNum != 00)       // Catch Case 0 just in case
    {
        switch(iRolledNum)    // Jump to the rolled statement number.
        {
        // Comment out unneeded lines in this section
            case 01:
                oTarget = GetWaypointByTag(sWaypoint1);
            break;
            case 02:
                oTarget = GetWaypointByTag(sWaypoint2);
            break;
            case 03:
                oTarget = GetWaypointByTag(sWaypoint3);
            break;
            case 04:
                oTarget = GetWaypointByTag(sWaypoint4);
            break;
            case 05:
                oTarget = GetWaypointByTag(sWaypoint5);
            break;
            case 06:
                oTarget = GetWaypointByTag(sWaypoint6);
            break;
            /*case 07:
                oTarget = GetWaypointByTag(sWaypoint7);
            break;
            case 08:
                oTarget = GetWaypointByTag(sWaypoint8);
            break;
            case 09:
                oTarget = GetWaypointByTag(sWaypoint9);
            break;
            case 10:
                oTarget = GetWaypointByTag(sWaypoint10);
            break;
            case 11:
                oTarget = GetWaypointByTag(sWaypoint11);
            break;
            case 12:
                oTarget = GetWaypointByTag(sWaypoint12);
            break;
            case 13:
                oTarget = GetWaypointByTag(sWaypoint13);
            break;
            case 14:
                oTarget = GetWaypointByTag(sWaypoint14);
            break;
            case 15:
                oTarget = GetWaypointByTag(sWaypoint15);
            break;
            case 16:
                oTarget = GetWaypointByTag(sWaypoint16);
            break;
            case 17:
                oTarget = GetWaypointByTag(sWaypoint17);
            break;
            case 18:
                oTarget = GetWaypointByTag(sWaypoint18);
            break;
            case 19:
                oTarget = GetWaypointByTag(sWaypoint19);
            break;
            case 20:
                oTarget = GetWaypointByTag(sWaypoint20);
            break;*/
        } // End Switch Statement
    }  // End If Statement
    else
    {
        // Assuming 0 should be invalid, set to desired waypoint
        // Change this to whatever the "Default value" the waypoint should be
        iRolledNum = 01;
        oTarget = GetWaypointByTag(sWaypoint1);
    }
    // Check to see if there is an Active TP, if not set to number being used.
    if (GetLocalString(oUser, "sRandomTPActive") == "")
    {
        // Build sDataString from group leader and iRollNum
        if (iRolledNum < 10)
        {
            sDataString = sGroupLeader+"0"+IntToString(iRolledNum);
        }
        else
        {
            sDataString = sGroupLeader+IntToString(iRolledNum);
        }
        // Now set sRandomTPActive on each party member
        oParty = GetFirstFactionMember(oUser);
        while(GetIsObjectValid(oParty))
        {
            SetLocalString(oParty, "sRandomTPActive", sDataString);
            oParty = GetNextFactionMember(oUser);
        }
    }
    // Count party members going in so you know when all leave, set variable on party.
    iTempCount = GetLocalInt(oUser, "iPartyCount");
    iTempCount++;
    oParty = GetFirstFactionMember(oUser);
    while(GetIsObjectValid(oParty))
    {
    SetLocalInt(oParty, "iPartyCount", iTempCount);
    oParty = GetNextFactionMember(oUser);
    }
    // Remember user's location so you can put them back at right door later.
    SetLocalLocation(oUser, "lRandomTPLoc", GetLocation(oUser));
    // Teleport command
    AssignCommand(oUser, JumpToObject(oTarget));
    // Ensure all "supporting cast" members go too.
    AssignCommand(GetAssociate(ASSOCIATE_TYPE_ANIMALCOMPANION, oUser), JumpToObject(oTarget));
    AssignCommand(GetAssociate(ASSOCIATE_TYPE_DOMINATED, oUser), JumpToObject(oTarget));
    AssignCommand(GetAssociate(ASSOCIATE_TYPE_FAMILIAR, oUser), JumpToObject(oTarget));
    AssignCommand(GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oUser), JumpToObject(oTarget));
    AssignCommand(GetAssociate(ASSOCIATE_TYPE_SUMMONED, oUser), JumpToObject(oTarget));
}  //End Main
/*//////////////////////////////////////////////
// exitrandomtp v2.1
////////////////////////////////////////////////
// Script by Jordinn, shea@oz.net
// Date Created: v1.0 7/16/02, v1.5 7/21/02, v2.0 8/28/02, v2.1 9/6/02
//////////////////////////////////////////////*/
#include "NW_O2_CONINCLUDE"
string ParseData(string sDataString, string sFlag)
{
    string sReturnVal;
    // This function parses the name and number stored in oUser
    // Data format expected STRINGnn
    if ((sDataString == "") || (sFlag == ""))
    {
        sReturnVal = "ERROR INVALID PARAMETERS";
    }
    else
    {
        if (sFlag == "i")
        {
            sReturnVal = GetStringRight(sDataString, 2);
        }
        else if (sFlag == "s")
        {
            sReturnVal = GetStringLeft(sDataString, (GetStringLength(sDataString)-2));
        }
        else
        {
            sReturnVal = "ERROR BAD FLAG";
        }
    }
    return sReturnVal;
}
// Main function
void main()
{
    // Declare Variables
    int iRandomFlag;
    int iTempCount;
    int iRandNum;
    location lTargetLoc;
    object oUser;
    object oContainer;
    object oArea;
    object oParty;
    float fDelay;
    // Get object that clicked, entered, or used the door to get out
    oUser = GetClickingObject();
    //  If using enter event, use this line
    // oUser = GetEnteringObject();
    //  If using conversation, use
    // oUser = GetPCSpeaker();
    // Set area to current
    oArea = GetArea(OBJECT_SELF);
    // Get Variables from User
    //iRandomFlag = StringToInt(ParseData(GetLocalString(oUser, "sRandomTPActive"), "i"));
    iTempCount = GetLocalInt(oUser, "iPartyCount");
    //Get lRandomTPLoc from the object
    lTargetLoc = GetLocalLocation(oUser, "lRandomTPLoc");
    //if not 0, decrement iTempCount
    if(iTempCount >= 1)
    {
        iTempCount--;
    }
    else
    {
        iTempCount = 0;
    }
    //if 0 set iRandomTPActive = 0
    if(iTempCount == 0)
    {
        SetLocalString(oUser, "sRandomTPActive", "");
        // Get nearest placeable object to generate treasure in
        oContainer = GetFirstObjectInArea(oArea);
        while (oContainer != OBJECT_INVALID)
        {
            if (GetObjectType(oContainer) == OBJECT_TYPE_PLACEABLE)
            {
                if (GetObjectType(oContainer) != OBJECT_TYPE_DOOR)
                {
                    //How long before the treasure will respawn, in seconds
                    fDelay = 45.0;
                    //Randomly choose value of treasure that will appear
                    iRandNum = d6(1);
                    switch(iRandNum)
                    {
                        case 1:
                        case 2:
                        case 3:
                            DelayCommand(fDelay, GenerateLowTreasure(oUser, oContainer));
                            break;
                        case 4:
                        case 5:
                            DelayCommand(fDelay, GenerateMediumTreasure(oUser, oContainer));
                            break;
                        case 6:
                            DelayCommand(fDelay, GenerateHighTreasure(oUser, oContainer));
                            break;
                    }
                }
            }
            // Randomly lock placeable objects on respawn
            iRandNum = d10(1);
            switch(iRandNum)
            {
        case 1:
        case 2:
        case 3:
            DelayCommand(fDelay+0.5, ActionDoCommand(SetLocked(oContainer, TRUE)));
            break;
        case 4:
        case 5:
        case 6:
        case 7:
        case 8:
        case 9:
        case 10:
            break;
        }
            oContainer = GetNextObjectInArea(oArea);
        }
    }
    //Reset Count on all users to correct number
    oParty = GetFirstFactionMember(oUser);
    while(GetIsObjectValid(oParty))
    {
        SetLocalInt(oParty, "iPartyCount", iTempCount);
        oParty = GetNextFactionMember(oUser);
    }
    //Jump To Location
    AssignCommand(oUser, JumpToLocation(lTargetLoc));
    //These lines will ensure all "supporting cast" members go too.
    AssignCommand(GetAssociate(ASSOCIATE_TYPE_ANIMALCOMPANION, oUser), JumpToLocation(lTargetLoc));
    AssignCommand(GetAssociate(ASSOCIATE_TYPE_DOMINATED, oUser), JumpToLocation(lTargetLoc));
    AssignCommand(GetAssociate(ASSOCIATE_TYPE_FAMILIAR, oUser), JumpToLocation(lTargetLoc));
    AssignCommand(GetAssociate(ASSOCIATE_TYPE_HENCHMAN, oUser), JumpToLocation(lTargetLoc));
    AssignCommand(GetAssociate(ASSOCIATE_TYPE_SUMMONED, oUser), JumpToLocation(lTargetLoc));
}
Advertisement