Author Topic: Encounter Scaling  (Read 311 times)

Legacy_The Mad Poet

  • Hero Member
  • *****
  • Posts: 715
  • Karma: +0/-0
Encounter Scaling
« on: September 07, 2013, 03:19:51 am »


               How do other people scale encounters to the party? I've been using the 'Scaled' prefix in NESS's group spawning. Seems to work ok, but I don't think I can get it to actually spawn a random group that is scaled to the party, only a random individual that is scaled to the group. This of course means that if I send more than one it's too much. And one creature can almost always be taken down by a group of four PC's. Unless someone else knows a good way to scale encounters with NESS I'm slowly losing my desire to keep using it as my players plow through relatively easy encounters.

I've tried using the bioware encounter system. Seems to work fairly well at scaling the encounter providing there is plenty of creatures of various CR's for it to work with. I like keeping with NESS and the flag options associated. I also don't like how seemingly hefty sized the encounters are when put in the game. I think I dropped 2 megs off my module size when i changed to NESS spawns, and that was just in four dungeons.

Have others tackled this? I'm trying to find the best way to keep my players challenged, but maintain randomness and good scaling with party level and size.
               
               

               


                     Modifié par The Mad Poet, 07 septembre 2013 - 02:23 .
                     
                  


            

Legacy_FunkySwerve

  • Hero Member
  • *****
  • Posts: 2325
  • Karma: +0/-0
Encounter Scaling
« Reply #1 on: September 07, 2013, 02:50:07 pm »


               We tackled this, and wound up using a custom encounter system. The bioware system breaks down at high CRs, and just wouldn't do what we wanted. We wound up going with a custom system, though, not NESS; one tailored to our specific wants. I can provide more information if you think you want to tackle that, but you might be better served by someone who uses NESS (or modifying it, if necessary).

Funky
               
               

               
            

Legacy_The Mad Poet

  • Hero Member
  • *****
  • Posts: 715
  • Karma: +0/-0
Encounter Scaling
« Reply #2 on: September 07, 2013, 05:00:01 pm »


               Well as of right now we're capped at level 20 until I finish enough content in those levels to move on to higher. I don't think I'll move beyond maybe level 25-30 at all anyway.

Modifying NESS would be fine, and I'd rather do that considering that I've got so much already setup in the module for it. Easier to edit a few than redo the encounters in every dungeon. Otherwise I'm willing to look at other options.
               
               

               
            

Legacy_ffbj

  • Hero Member
  • *****
  • Posts: 1097
  • Karma: +0/-0
Encounter Scaling
« Reply #3 on: September 07, 2013, 06:36:11 pm »


                I used to use Ness for SGW (Second God War).  Later I developed my own method.
Here is 1 example:

#include "NW_I0_GENERIC" 
#include "x3_inc_string" 
#include "_prr_skillcheck"
 #include "sy_inc_random"
void main()    {        int nCreature, nNumber;        string sCreature = "";        string sSoundName = "as_an_wolfhowl2";        string sMessage = (StringToRGBString("\\n AMBUSH !! \\n",STRING_COLOR_RED));         string sMessage1 = (StringToRGBString("\\n ASSASSIN !! \\n",STRING_COLOR_GREEN)); 
      object oPCfpc = GetFirstPC(); 
      object oPCL = GetFactionLeader(oPCfpc); 
      object oArea = GetArea(oPCL); 
      int iHD = GetHitDice(oPCL); 
      int iMembers = GetLocalInt(oPCL,"Members");
        if  (GetLocalInt(oPCL,"Safe") == 1)        return; 
      //in certain areas which are patrolled or guarded the on enter of the area will set the local Safe on the PC to prevent        //spawn scripts from running. 
       if  ((iHD +d4()  > 16) &&(GetLocalInt(oArea, "SpawnNO16") == 1))        return; 
      //some areas you don't want higher level creatures spawning...areas near the starting zones.  These lines check for a local on the   
    //area which return the script.  What could happen would be that a higher level character has left a zone and is going back towards        //areas where lower levels reside.  These lines return the script if local SpawnNO16 is set to 1. 
       if  ((iHD +d4() > 20) &&(GetLocalInt(oArea, "SpawnNO20") == 1))        return;   
    //same idea here but for a little higher level. pc 
      while (oArea != GetArea(oPCL))
                {                 oPCfpc =  GetNextPC();                }
       if (GetLocalInt(oPCL,"Ran") > 2 +d4(1))         return;
//script will only run 3 times,plus d4 default would be 4

           //if (GetDetectMode(oPC) == DETECT_MODE_PASSIVE)//not actively searching.          //return;          //if ( GetStealthMode( oPC ) == STEALTH_MODE_ACTIVATED ) 
        //not in use currently but for reference if you want to adjust spawns according to stealth condition of the pc          //also used elsewhere in script     
  object oTarget = oPCL;   
    int iSpot = GetSkillRank(SKILL_SPOT, oTarget); 
      int iListen = GetSkillRank(SKILL_LISTEN, oTarget); 
      int iSearch = GetSkillRank(SKILL_SEARCH, oTarget); 
      int iDetect = (iSpot + iListen +iSearch/3);     
  int iHour = GetTimeHour(); 
      int iHd = GetHitDice(oPCL);     
  int nRandomI = 6;   
    float fDistance = 5.0 + (iHd/2 + d4 (3));//higher level notice things futher away 
      location lWP = GetRandomLocation(oArea,oTarget,fDistance); 
      location lTarget = GetLocation(oTarget);
        if (GetIsObjectValid(oPCL)&&(oArea == GetArea(OBJECT_SELF)))
            //Cycle through PCs party members in the area            {
             object oPMember = GetFirstFactionMember(oPCL, TRUE);
             while (GetIsObjectValid(oPMember) && (oArea == GetArea(oPCL)))     
       {             if (oArea != GetArea(oPCL))       
         {                 oPMember =  GetNextFactionMember(oPCL, TRUE);                 }
             iHd++;             iHd += GetHitDice(oPMember);     
       //trying to add the pc's in the area hp   
         SetLocalInt(oPCL,"Members", GetLocalInt(oPCL,"Members")+1);     
       oPMember = GetNextFactionMember(oPCL, TRUE);             }
             //scales spawns in relationship to power of the party     
       if (iHd < 16)                SetLocalInt(oPCL,"Spawn",1);     
      else if (iHd < 24)                SetLocalInt(oPCL,"Spawn",2);   
        else if (iHd < 36)                SetLocalInt(oPCL,"Spawn",3); 
          else if (iHd < 44)                SetLocalInt(oPCL,"Spawn",4);   
        else                SetLocalInt(oPCL,"Spawn",5);   
        if ((iDetect > d8(2)+iHd/2 && (GetDetectMode(oPCL) == DETECT_MODE_ACTIVE)&& (GetIsNight())) )             {             //ambush detected proceed accordingly       
    SetLocalInt(oPCL,"Ambush", GetLocalInt(oPCL,"Ambush") - iHd/6); 
          GiveXPToCreature(oPCL, iHd/2 + iDetect * 2);       
    FloatingTextStringOnCreature(" Ambush Detected and Avoided !", oPCL,TRUE); 
          (SetLocalInt(oPCL,"Ran", GetLocalInt(oPCL,"Ran") + 2));     
       return;             }   
        if ((iHd > 8) ||  (GetLocalInt(oPCL,"Members") > 1))            SetLocalInt(oPCL,"Ambush", GetLocalInt(oPCL,"Ambush") + iHd/4);            if (GetLocalInt(oPCL,"Members") > 3)            SetLocalInt(oPCL,"Ambush", GetLocalInt(oPCL,"Ambush") + iHd/2); 
          if ((GetStealthMode(oPCL) == STEALTH_MODE_DISABLED) && (GetIsNight ()))            {                SetLocalInt(oPCL,"Spawn", GetLocalInt(oPCL,"Spawn")+2);   
            FloatingTextStringOnCreature("You Have Been Detected!", oPCL,TRUE);                SetLocalInt(oPCL,"Ambush", GetLocalInt(oPCL,"Ambush") +1);                DelayCommand (3.0, AssignCommand(oPCL,PlaySound(sSoundName)));                DelayCommand (6.0, ExecuteScript("spawnwolves",oArea));                //the wolf spawn is a script that will alert pc's to the fact they are detected            }              if (d20(5) > (40 + iHd + nRandomI))
                 {                  DelayCommand (1.5,SendMessageToPC(oPCL, " Something is running away! "));                  SetLocalInt(oPCL,"Ambush", GetLocalInt(oPCL,"Ambush") -nRandomI);                 }            
           if ( GetStealthMode( oPCL ) == STEALTH_MODE_ACTIVATED )   
            SetLocalInt(oPCL,"Spawn", GetLocalInt(oPCL,"Spawn")-1);     
          SetLocalInt(oPCL,"Ambush", GetLocalInt(oPCL,"Ambush") -1);     
      if (GetDetectMode(oPCL) == DETECT_MODE_ACTIVE)       
         SetLocalInt(oPCL,"Spawn", GetLocalInt(oPCL,"Spawn")-1);     
           SetLocalInt(oPCL,"Ambush", GetLocalInt(oPCL,"Ambush") -2);   
        if ( GetLocalInt(oArea,"SpawnLess")== 1)       
    //if local on are SpawnLess set to 1 lower the spawn table.   
            SetLocalInt(oPCL,"Spawn", GetLocalInt(oPCL,"Spawn")-2);   
            SetLocalInt(oPCL,"Ambush", GetLocalInt(oPCL,"Ambush") -3);   
        if   ((GetTimeHour() >0 < 6) && (d4(2) > 5))       
         {                 SetLocalInt(oPCL,"Spawn", GetLocalInt(oPCL,"Spawn")+1);                 }   
             //bad things happen at night         
     if ((GetLocalInt(oPCL,"Spawn")== 1) && (GetIsSkillSuccessful(oPCL, SKILL_LISTEN, 12  -d4(3))))//easy
                      {                      SendMessageToPC(oPCL, "You Hear Something!");                      GiveXPToCreature(oPCL, 25 -nRandomI);
                       switch (d6())                           
 {                         case 1: sCreature = "moordeer"; break;//resref of creature   
                           case 2: sCreature = "madcrow"; break;         
                           case 3: sCreature = "goblinarcher"; break;                     
                           case 4: sCreature = "skeletondart"; break;                     
                           case 5: sCreature = "moorwof"; break;                       
                           case 6: sCreature = "skeletonrapier"; break;                     
        }                        for (nNumber = 0; nNumber < d2(); nNumber++)                        CreateObject(OBJECT_TYPE_CREATURE, sCreature, lWP, FALSE);
                     object oCreature = GetNearestObjectToLocation(OBJECT_TYPE_CREATURE, lWP);     
               float fDistance1 = GetDistanceBetweenLocations(lWP, lTarget);   
                 string sDistance = FloatToString(fDistance1, 2,0); 
                   DelayCommand (0.5,SendMessageToPC(oPCL, " Some noise, over there! " + sDistance + " metres away."));       
             DelayCommand (5.0, TurnToFaceObject(oCreature, oPCL));                     return;                         }

                      if  ((GetLocalInt(oPCL,"Spawn")== 2) && (GetIsSkillSuccessful(oPCL, SKILL_SPOT, 16  -d4(2))))//harder                       
   {                            SendMessageToPC(oPCL, "You See Something!");                            GiveXPToCreature(oPCL, 30 -nRandomI);                            SetLocalInt(oPCL,"Spawn", GetLocalInt(oPCL,"Spawn")+1);                             switch (d6())//should be tougher creatures below                               {                            case 1: sCreature = "moordeer"; break;//resref of creature                            case 2: sCreature = "orcfighter"; break;                            case 3: sCreature = "goblinarcher"; break;                            case 4: sCreature = "goblinscout"; break;                            case 5: sCreature = "moorwof"; break;                            case 6: sCreature = "goblinraider"; break;                               }
                    //Randomly generate the number of monsters//                      for (nNumber = 0; nNumber < d3(); nNumber++)//change d4 for more                      CreateObject(OBJECT_TYPE_CREATURE, sCreature, lWP, FALSE);                     object oCreature = GetNearestObjectToLocation(OBJECT_TYPE_CREATURE, lWP);                     float fDistance1 = GetDistanceBetweenLocations(lWP, lTarget);                     string sDistance = FloatToString(fDistance1, 2,0);                     DelayCommand (0.5,SendMessageToPC(oPCL, " Something, over there! " + sDistance + " meters away."));                     DelayCommand (4.0, TurnToFaceObject(oCreature, oPCL));                          }                      else if ((GetStealthMode(oPCL) == STEALTH_MODE_DISABLED) && (d100 () > 45 +iHd) && (GetLocalInt(oPCL,"Ambush") < 4)&& (iHd < 12))                       {                      CreateObject(OBJECT_TYPE_CREATURE, "banditrogue", lWP, TRUE);                      SetLocalInt(oPCL,"Ambush", GetLocalInt(oPCL,"Ambush") +1);                       }                       {                        if ((GetLocalInt(oPCL,"Spawn")==3) && (GetIsSkillSuccessful(oPCL, SKILL_LISTEN, 20  -d4(1))))
                             {                              SendMessageToPC(oPCL, "A faint sound reaches you!");                              GiveXPToCreature(oPCL, 40 +nRandomI);                              SetLocalInt(oPCL,"Spawn", GetLocalInt(oPCL,"Spawn")+1);                              switch (d6())                                {                            case 1: sCreature = "dwarvenaxe"; break;//resref of creature                            case 2: sCreature = "orcfighter"; break;                            case 3: sCreature = "goblinraider"; break;                            case 4: sCreature = "goblinscout"; break;                            case 5: sCreature = "timberwolf"; break;                            case 6: sCreature = "goblinhero"; break;                                }                        for (nNumber = 0; nNumber < d2(); nNumber++)                        CreateObject(OBJECT_TYPE_CREATURE, sCreature, lWP, FALSE);                       object oCreature = GetNearestObjectToLocation(OBJECT_TYPE_CREATURE, lWP);                     float fDistance1 = GetDistanceBetweenLocations(lWP, lTarget);                     string sDistance = FloatToString(fDistance1, 2,0);                     DelayCommand (0.5,SendMessageToPC(oPCL, " Something is moving, over there! " + sDistance + " metres away."));                     DelayCommand (5.0, TurnToFaceObject(oCreature, oPCL));                            }
                        else if ((GetStealthMode(oPCL) == STEALTH_MODE_DISABLED) && (GetIsNight ()) && (GetLocalInt(oPCL,"Ambush") > 4) && (d100 () > 50 +iHd) && (iHd > 8))                      {                      CreateObject(OBJECT_TYPE_CREATURE, "vagabond", lWP, TRUE);                      SetLocalInt(oPCL,"Ambush", GetLocalInt(oPCL,"Ambush") + 2);                      DelayCommand (20.0 +iHd, SetLocalInt(oPCL,"Ambush", GetLocalInt(oPCL,"Ambush") -1));                      }
                     if ((GetLocalInt(oPCL,"Spawn") == 4) &&  (GetIsSkillSuccessful(oPCL, SKILL_LISTEN, 22  -d4(2))))//etc...
                             {                            SendMessageToPC(oPCL, "Your highly attuned senses are alerted!");                             GiveXPToCreature(oPCL, 60 -nRandomI);                             SetLocalInt(oPCL,"Ambush", GetLocalInt(oPCL,"Ambush") -1);                             SetLocalInt(oPCL,"Members", GetLocalInt(oPCL,"Members")-1);                            switch (d6())//should be tougher creatures                               {                            case 1: sCreature = "goblinhero"; break;//resref of creature                            case 2: sCreature = "helongbowman"; break;                            case 3: sCreature = "goblinraider"; break;                            case 4: sCreature = "spidgian002"; break;                            case 5: sCreature = "orchero"; break;                            case 6: sCreature = "goblinscout"; break;                               }                        for (nNumber = 0; nNumber < 3; nNumber++)                    CreateObject(OBJECT_TYPE_CREATURE, sCreature, lWP, FALSE);                    object oCreature = GetNearestObjectToLocation(OBJECT_TYPE_CREATURE, lWP);                    float fDistance1 = GetDistanceBetweenLocations(lWP, lTarget);                    string sDistance = FloatToString(fDistance1, 2,0);                    DelayCommand (1.0,SendMessageToPC(oPCL, " Some movement, over there! " + sDistance + " metres away."));                    DelayCommand (5.0, TurnToFaceObject(oCreature, oPCL));                           }
                      else if ((GetStealthMode(oPCL) == STEALTH_MODE_DISABLED) && (GetIsNight ()) && (GetLocalInt(oPCL,"Ambush") > 6) && (d100 () > 75 -iHd) && (iHd > 10))                      {                      CreateObject(OBJECT_TYPE_CREATURE, "banditmarksman", lWP, FALSE);                       DelayCommand (1.0, FloatingTextStringOnCreature(sMessage, oPCL, FALSE));                       SetLocalInt(oPCL,"Ambush", GetLocalInt(oPCL,"Ambush") + 1);                      DelayCommand (15.0 +iHd, SetLocalInt(oPCL,"Ambush", GetLocalInt(oPCL,"Ambush") -2));
                      }
                     if ((GetLocalInt(oPCL,"Spawn") == 5) &&  (GetIsSkillSuccessful(oPCL, SKILL_SPOT, 30 -d4(3))) &&(GetIsSkillSuccessful(oPCL, SKILL_LISTEN, 30  -d4 (3))))//etc...
                           {                            SendMessageToPC(oPCL, "Your highly attuned senses are alerted!");                            GiveXPToCreature(oPCL, 100 - iHd);                            SetLocalInt(oPCL,"Ambush", GetLocalInt(oPCL,"Ambush") -2);                            SetLocalInt(oPCL,"Members", GetLocalInt(oPCL,"Members")-1);                            switch (d6())//should be tougher creatures                               {                            case 1: sCreature = "drowscout"; break;//resref of creature                            case 2: sCreature = "orchero"; break;                            case 3: sCreature = "spidgian002"; break;                            case 4: sCreature = "harpie002"; break;                            case 5: sCreature = "ogrefighter"; break;                            case 6: sCreature = "dwarvenaxe"; break;                               }                     for (nNumber = 0; nNumber < 3; nNumber++)                     CreateObject(OBJECT_TYPE_CREATURE, sCreature, lWP, FALSE);                    object oCreature = GetNearestObjectToLocation(OBJECT_TYPE_CREATURE, lWP);                    float fDistance1 = GetDistanceBetweenLocations(lWP, lTarget);                    string sDistance = FloatToString(fDistance1, 2,0);                    DelayCommand (1.0,SendMessageToPC(oPCL, " A flash of movement, over there! " + sDistance + " metres away."));                    DelayCommand (5.0, TurnToFaceObject(oCreature, oPCL));                          }                     else if ((GetStealthMode(oPCL) == STEALTH_MODE_DISABLED) && (GetIsNight ()) && (GetLocalInt(oPCL,"Ambush") > 8) &&  (iHd > 13))                      {                      CreateObject(OBJECT_TYPE_CREATURE, "banditass", lWP, TRUE);                      DelayCommand (2.5, FloatingTextStringOnCreature(sMessage1, oPCL, FALSE));                      SetLocalInt(oPCL,"Ambush", GetLocalInt(oPCL,"Ambush") + 1);                      }



      SetLocalInt(oPCL,"Ran", GetLocalInt(oPCL,"Ran")+1);      DelayCommand (400.0/d4(1), ExecuteScript("randomspslisten",oArea));      DelayCommand (250.0, DeleteLocalInt(oPCL,"Members"));      DelayCommand (500.0, DeleteLocalInt(oPCL,"Ran"));      //in order to reset the script after some time has passed.      }      }
}
I think you can just remove the prr skill check include, since it just changes the way skill checks are made, and it would still work.  Of course you would to input your own creatures.  The basic approach/idea is that normally there is no differnetiation in the how, too's and wherefores of why things spawn.  With my method there is much greater range of results dependent on party size, time of day, stealth/awareness. 
My orginal random spawning script:
http://nwvault.ign.c....detail&id=3318
               
               

               


                     Modifié par ffbj, 07 septembre 2013 - 05:53 .
                     
                  


            

Legacy_The Mad Poet

  • Hero Member
  • *****
  • Posts: 715
  • Karma: +0/-0
Encounter Scaling
« Reply #4 on: September 08, 2013, 02:28:42 am »


               Thanks. I think I might try playing around with rewriting the scale functions in NESS for the moment. Your script gave me some ideas.