Random Encounters



  • Was working on this for my own purposes, but figured I'd share in case folks were looking for something similar to CoA's CARES.

    /////////////Escape From Underdark Randomized-Encounters (EFURY)
    /////////////Author : RavenBlackRose/Seth Carter
    /////////////Date: 07/10/2005
    /////////////Updated for Isles of Elysium
    ////////////////////////////////////////////////////
    /////////////New Version Akylonor 2010, d100 Odds.
    /////////////Called From:Area OnEnter
    
    void SpawnEncounter(string sSpawn, location lSpawn)
    {
        string sDebugSpawn = "Encounter String:'" + sSpawn + "', ";
        string sSubstring;
        string sCritter;
        //string reading function
        int iPositionInString = 0;
        int iStringLength = GetStringLength(sSpawn);
        int iPositionInSubString = 0;
        int iSubStringLength;
        int iLastStop = 0;
        int iMultipleCreatures;
        int iCounter;
        int iFoundInSubstring;
        //read through the string
        while(iPositionInString != iStringLength)
        {
            //stop at |
            if(GetSubString(sSpawn, iPositionInString, 1) == "|")
            {
                //get the creature substring
                sSubstring = GetSubString(sSpawn, iLastStop, iPositionInString-iLastStop);
                sDebugSpawn += "Creature Substring: '" + sSubstring +"', ";
                iLastStop = iPositionInString+1; //move the stop to the character after "|"
                iMultipleCreatures = 1; //reset the check for a multiple creatures
                //read through the substring
                iPositionInSubString = 0;
                iSubStringLength = GetStringLength(sSubstring);
                iFoundInSubstring = 0;
                while(iPositionInSubString != iSubStringLength)
                {
                    if(GetSubString(sSubstring, iPositionInSubString, 1) == "*")
                    {
                        sCritter = GetSubString(sSubstring, 0, iPositionInSubString);
                        iMultipleCreatures = StringToInt(GetSubString(sSubstring, GetStringLength(sCritter)+1, GetStringLength(sSubstring)-(GetStringLength(sCritter)+1)));
                        iFoundInSubstring =1;
                    }
                    else
                    {
                        if(iFoundInSubstring != 1)
                        {
                            sCritter = sSubstring;
                        }
                    }
    
                    iPositionInSubString++;
                }
                 //spawning function (complex, ain't it)
                    if(iMultipleCreatures == 1)
                    {
                       CreateObject(OBJECT_TYPE_CREATURE, sCritter, lSpawn, FALSE);
                    }
                    else
                    {
                        for(iCounter = 0; iCounter < iMultipleCreatures; iCounter++)
                        {
                           CreateObject(OBJECT_TYPE_CREATURE, sCritter, lSpawn, FALSE);
                        }
                    }
            }
            iPositionInString ++;
        }
        WriteTimestampedLogEntry(sDebugSpawn);
    }
    
    void main()
    {
        string sLocationDebug;
        //load area, and dice
        object oArea = OBJECT_SELF;
        object oPC = GetEnteringObject();
        int iLocationDice = GetLocalInt(oArea, "efury_spawnpoints");
        int iSpawnDice = d100(1);
        int iCondition = iLocationDice;
        int iCounter = 0;
        int iEncounterOdds;
        int nOddsCounter;
        int iEncounterChosen = 0;
        //avoid bombarding parties
        if(GetLocalInt(oArea, "RecentSpawned") == 0)
        {
        if(GetIsPC(oPC)) //prevents multispawns from companions, other monsters, DM's wandering about, etc
        {
            //run for as many times as there are possible spawnpoints
            iCounter = 1;
            while(iCounter 


  • Yeah, I advanced this further, later on. (2 posts here, doesn't all fit in one)

    I'll put the script block in a second post, since it's a relatively large one. It's a system I made (as can be seen in the notes) for Escape from the Underdark eons and eons ago, though its altered vastly from that primitive work.

    Essentially, you can either tie the system to an Area OnEnter, or a Trigger OnEnter (or both, if you really want). When these are fired, it goes through waypoints in the area tagged as "WP_spawnpoint_" with a number on the end (1 to whatever your system can handle before timing out, or the end of integers I suppose, but its unlikely any area has enough spawns for either case)

    On each of these waypoints, are stored a variable list, as shown in this picture (This may seem a lot of work, but you can cut and paste them through an area fast if its similar, or even make Pre-Made Tables by creating them in the pallette for use all over the place)

    To dissect this down.

    "respawn_time" is the time in seconds it will take before the script will zap through again. Keeps parties from flooding over and such. Although its on the waypoints (for future use), it presently affects the entire area (the last waypoint will be the used setting).

    "encounter_#" is a defined encounter. The semi-gibberish there is four orcs with a shaman, 3 wolves, a mixed spiders/ettercap, a great wyvern, and "null" denotes a blank encounter, used for odds of nothing whatsoever spawning. The syntax used is

    *|
    ^ A resref is not a tag. You can find it under the Advanced Tab of creature properties (for Default NWN monsters, put one down in an area, then check, as Edit Copy will alter it) 
    ```. Even for singles you need the *1, and the | has to follow each creature, even the last.
    
    ""enc_chance_#" is the odds assigned to an encounter. For efficiencies sake, you start with your largest chance encounter (you don't have to order them at all, but its helpful). The odds aren't percantile, due to the script logic, but rather reflect a range on a d100\. 1-(enc_chance_1) will give you encounter_1\. enc_chance_1 plus 1 through to enc_chance_2's odds will give you encounter_2, and so on.
    
    In the sample case, the orcs spawn on a roll of 1-25 (25%), the wolves on a roll of 26-50(25%), the spider group on a roll of 51-70,(20%), the wyvern on a roll of 71-80 (10%), and no monsters on a roll of 81-100 (20%)
    
    For efficiency and organization, you should cover all 100 odds, lead with the largest chance (since that'll avoid extra script loops, though I've tried it with 25 encounters on a spawn point to no noticeable lag) and work your way down to the minute ones, but the script has limits throughout (denoted in comments) to avoid nasty TMIs from that double loop used)
    
    You also don't need to have a null encounter at all, if you want to cover all 100 possibilities with various monsters, something will always spawn.


  • /////////////Seth's Random Encounters
    /////////////Author : BlackRose/Seth Carter
    /////////////Date: 07/10/2005, Update May 2007, Update August 2010, Update Jan 2011
    /////////////If this wasn't posted or directly distributed to you, it ain't yours. To date including Escape From The Underdark, Isles of Elysium, Bid For Transcendence, Akrylonor, Cormyr & Dales
    /////////////New Version 2010, d100 Odds.
    /////////////Called From:Area or Trigger OnEnter
    
    void SpawnEncounter(string sSpawn, location lSpawn)
    {
        string sDebugSpawn = "Encounter String:'" + sSpawn + "', ";
        string sSubstring;
        string sCritter;
        //string reading function
        int iPositionInString = 0;
        int iStringLength = GetStringLength(sSpawn);
        int iPositionInSubString = 0;
        int iSubStringLength;
        int iLastStop = 0;
        int iMultipleCreatures;
        int iCounter;
        int iFoundInSubstring;
        //read through the string
        while(iPositionInString != iStringLength)
        {
            //stop at |
            if(GetSubString(sSpawn, iPositionInString, 1) == "|")
            {
                //get the creature substring
                sSubstring = GetSubString(sSpawn, iLastStop, iPositionInString-iLastStop);
                sDebugSpawn += "Creature Substring: '" + sSubstring +"', ";
                iLastStop = iPositionInString+1; //move the stop to the character after "|"
                iMultipleCreatures = 1; //reset the check for a multiple creatures
                //read through the substring
                iPositionInSubString = 0;
                iSubStringLength = GetStringLength(sSubstring);
                iFoundInSubstring = 0;
                while(iPositionInSubString != iSubStringLength)
                {
                    if(GetSubString(sSubstring, iPositionInSubString, 1) == "*")
                    {
                        sCritter = GetSubString(sSubstring, 0, iPositionInSubString);
                        iMultipleCreatures = StringToInt(GetSubString(sSubstring, GetStringLength(sCritter)+1, GetStringLength(sSubstring)-(GetStringLength(sCritter)+1)));
                        iFoundInSubstring =1;
                    }
                    else
                    {
                        if(iFoundInSubstring != 1)
                        {
                            sCritter = sSubstring;
                        }
                    }
    
                    iPositionInSubString++;
                }
                 //spawning function (complex, ain't it)
                    if(iMultipleCreatures == 1)
                    {
                       CreateObject(OBJECT_TYPE_CREATURE, sCritter, lSpawn, FALSE);
                    }
                    else
                    {
                        for(iCounter = 0; iCounter < iMultipleCreatures; iCounter++)
                        {
                           CreateObject(OBJECT_TYPE_CREATURE, sCritter, lSpawn, FALSE);
                        }
                    }
            }
            iPositionInString ++;
        }
        WriteTimestampedLogEntry(sDebugSpawn);
    }
    
    void main()
    {
    ///    string sLocationDebug; DEBUG ONLY
        //load area, and initialize dice
        object oArea;
        //// If I'm a Trigger, get my area, else I should be the area
        if(GetObjectType(OBJECT_SELF) == OBJECT_TYPE_TRIGGER) { oArea = GetArea(OBJECT_SELF); } else { oArea = OBJECT_SELF; }
        object oPC = GetEnteringObject();
        int iLocationDice = GetLocalInt(oArea, "Number_Of_Spawnpoints"); // Not strictly necessary, but putting this variable on the area will stop it at that many points, and avoid a very rare TMI
        int iSpawnDice = d100(1);
        int iCondition = iLocationDice;
        int iCounter = 0;
        int iEncounterOdds;
        int nOddsCounter;
        int iEncounterChosen = 0;
        //avoid bombarding the place when a group enters and don't spawn stuff if a DM turned encounters off
        if(GetLocalInt(oArea, "RecentSpawned") == 0 && GetLocalInt(oArea, "DMENCOFF") == 0)
        {
        if(GetIsPC(oPC) && GetIsDM(oPC) == FALSE) //prevents multispawns and potential TMIS and massive lags from companions, other monsters, DM's wandering about, etc
                            //////Strangely, a DM will register as a PC without this second check
        {
            //run for as many times as there are possible spawnpoints
            iCounter = 1; // Initialize Counter
            string sLocation = "WP_spawnpoint_" + IntToString(iCounter); // Start with the first spawnpoint
            object oSpawnPoint = GetNearestObjectByTag(sLocation, oPC); // Grab our first waypoint, for added accuracy (cause nwn is occasionally random about it, start from the PC triggering)
            while(iCounter 

Log in to reply