Author Topic: Requirement of at least X levels in every class  (Read 310 times)

Legacy_Grani

  • Hero Member
  • *****
  • Posts: 1040
  • Karma: +0/-0
Requirement of at least X levels in every class
« on: November 21, 2014, 11:18:12 pm »


               

Hello!


I mentioned some time ago in one of the topics that I want to have players in my module at least 10 levels in every of their classes by the time they reach the maximum level, which is level 40.


Somebody asked me how I'm going to enforce this and I said that I didn't plan to, since it's only a singleplayer/LAN module anyway. No scripted restrictions required, just an "agreement".


 


Still, I ultimately thought it would feel more professional if I did such an enforcement.


When I came around to writing this function, I decided it would be more useful if I allowed the builder to have any minimum they wish and not just level 10. And, of course, I needed to take into account that PDK and Harper Scout classes should not be subject to this enforcement, since it's impossible to have 6 or more levels invested in them.


So, here it is, a function that's supposed to handle this enforcement.


Aaand well, it doesn't work. '<img'> And by this I don't mean it JUST doesn't work, it actually crashes the game. And I'm not even sure what is it that I could have screwed up SO badly.


The game allows me to level in every case, no matter what levels and classes my PC has.



// Enforce that the PC will have at least a given number of levels in every
// class by the time he/she reaches the maximum level allowed in a module.
// If a PC gains a level that would make the above impossible,
// the level-up is cancelled and the script stops.
// Use at the beginning of an OnLevelUp script.
// This function can also be used to limit maximum level allowed in a module.
// - oPC: the levelling player
// - nMinLevel: the minimum number of levels in every class
// - nPossibleLevel: maximum character level allowed in a module
void EnforceAllowedLevel(object oPC, int nMinLevel, int nPossibleLevel = 40);

void EnforceAllowedLevel(object oPC, int nMinLevel, int nPossibleLevel = 40)
{
    //Declare variables
    int nMaxLevel;
    int nClass1 = -1;
    int nClass2 = -1;
    int nClass3 = -1;
    int nLevelDenied = 1;
    int nPCclass;
    int nClass1Levels;
    int nClass2Levels;
    int nClass3Levels;
    int nMinLevelC2;
    int nMinLevelC3;
    int nMinLevelPDK;

    //Determine maximum level possible to reach in a single class when multiclassing in 3 classes
    nMaxLevel = nPossibleLevel-2*nMinLevel;

    //Store PC's classes as variables (could have used GetLevelByPosition here, but I don't trust that function and it's not needed here)
    for (nPCclass = 0; nPCclass < 42; nPCclass++)
    {
        if (GetLevelByClass(nPCclass, oPC) != 0)
        {
        if (nClass1 == -1) nClass1 = nPCclass;
        else if (nClass2 == -1) nClass2 = nPCclass;
        else nClass3 = nPCclass;
        }
    }

    //Store levels in each of the PC's class as variables
    nClass1Levels = GetLevelByClass(nClass1, oPC);
    if (nClass2 != -1) nClass2Levels = GetLevelByClass(nClass2, oPC);
    else nClass2Levels = 0;
    if (nClass3 != -1) nClass3Levels = GetLevelByClass(nClass3, oPC);
    else nClass3Levels = 0;

    //A special case - if nMinLevel is greater than 5, allow PCs to have only 5 levels of a Knight or/and a Harper class anyway
    nMinLevelC2 = nMinLevel;
    nMinLevelC3 = nMinLevel;
    nMinLevelPDK = nMinLevel;
    if (nMinLevel < 5)
        {
            if (nClass2 == CLASS_TYPE_HARPER || nClass2 == CLASS_TYPE_PURPLE_DRAGON_KNIGHT) { nMinLevelC2 = 5; nMinLevelPDK = 5; }
            if (nClass3 == CLASS_TYPE_HARPER || nClass3 == CLASS_TYPE_PURPLE_DRAGON_KNIGHT) { nMinLevelC3 = 5; nMinLevelPDK = 5; }

        }

    //Accept the level-up if the PC doesn't multiclass and hasn't crossed a limit of the maximum possible level in a module
    if (nClass2 == -1 && GetHitDice(oPC) <= nPossibleLevel) nLevelDenied = 0;

    //Accept the level-up if the PC multiclasses in two classes and still allows both classes to have at least the required number of levels by the maximum level possible in the module (nMinLevel)
    else if ( (nClass3 == -1) && (nClass1Levels <= (nPossibleLevel-nMinLevelPDK)) && (nClass2Levels <= (nPossibleLevel-nMinLevel)) && GetHitDice(oPC) <= nPossibleLevel  ) nLevelDenied = 0;

    //Determine if the PC is allowed this level-up if the PC has 3 classes
    else if ( (nClass1Levels <= nMaxLevel) && (nClass2Levels <= nMaxLevel) && (nClass3Levels <= nMaxLevel) )
        {
            if (nClass1Levels < nMinLevel) nClass1Levels = nMinLevel;
            if (nClass2Levels < nMinLevel || nClass2Levels != 0) nClass2Levels = nMinLevelC2;
            if (nClass3Levels < nMinLevel || nClass3Levels != 0) nClass3Levels = nMinLevelC3;

            if (nClass1Levels + nClass2Levels + nClass3Levels <= nPossibleLevel) nLevelDenied = 0;
        }

    //Cancel the level-up if need be
    if (nLevelDenied == 1)
        {
            int nLevel = GetHitDice(oPC);
            int nXP = GetXP(oPC);
            int nAlpha = nXP;
            if (nXP < 200)
            {
                SetXP(oPC, 1);
            }
            while (GetHitDice(oPC) == nLevel)
            {
                nAlpha -= 200;
                SetXP(oPC, nAlpha);
            }
            FloatingTextStringOnCreature("You can't level in this class anymore!", oPC, TRUE);
            DelayCommand(3.0f, SetXP(oPC ,nXP));
            return;
        }
}

Edit: The previous problem of the game always stopping me from levelling was due to a single "=" sign in an "if" statement that I missed earlier. Now that I've fixed it, I get the opposite problem. The game always lets me level-up. '<img'>



               
               

               
            

Legacy_Lightfoot8

  • Hero Member
  • *****
  • Posts: 4797
  • Karma: +0/-0
Requirement of at least X levels in every class
« Reply #1 on: November 22, 2014, 05:28:16 am »


               

I have not tested it.   But try this function,   


 




// Enforce that the PC will have at least a given number of levels in every
// class by the time he/she reaches the maximum level allowed in a module.
// If a PC gains a level that would make the above impossible,
// the level-up is cancelled and the script stops.
// Use at the beginning of an OnLevelUp script.
// This function can also be used to limit maximum level allowed in a module.
// - oPC: the levelling player
// - nMinLevel: the minimum number of levels in every class
// - nPossibleLevel: maximum character level allowed in a module
void EnforceAllowedLevel(object oPC, int nMinLevel, int nPossibleLevel = 40);


void EnforceAllowedLevel(object oPC, int nMinLevel, int nPossibleLevel = 40)
{


  // First check to see if there is even more then one class. If there is not abort.
  if (GetClassByPosition(2,oPC) == CLASS_TYPE_INVALID) return;


  //Figure out how many optional levels the player gets.
  int nOptLevels = 3;
  if (GetClassByPosition(3,oPC) == CLASS_TYPE_INVALID) nOptLevels = 2;
  nOptLevels = nPossibleLevel - nOptLevels * nMinLevel;


  // Handle HARPER  PURPLE_DRAGON_KNIGHT cases.
  // I dont Know the Pres-Classes that well.  Im Assuming that you can not be both.
  int bDelevel = FALSE;
  int nlevel = GetLevelByClass(CLASS_TYPE_HARPER,oPC)
               +GetLevelByClass(CLASS_TYPE_PURPLE_DRAGON_KNIGHT);
  if (nlevel > 5) bDelevel = TRUE;
  else if( nlevel >0 && nMinLevel> 5) nOptLevels +=  nMinLevel - 5;


  //count up the number of opt levels alredy taken.
  int nOptLevelsTaken;
  int x;
  for (x=1;x<4;x++)
  {
    nlevel = GetClassByPosition(x,oPC)-nMinLevel;
    if ( nlevel >0) nOptLevelsTaken += nlevel;
  }


  //Check to see if deleveling is needed.
  if (nOptLevelsTaken >nOptLevels || bDelevel == TRUE)
  {
    // Delevel PC.
    int nXP = GetXP(oPC);
    int nHD = GetHitDice(oPC);


    SetXP(oPC, (nHD* nHD -nHD)*500);
    SetXP(oPC, nXP);
  }


}


               
               

               
            

Legacy_Grani

  • Hero Member
  • *****
  • Posts: 1040
  • Karma: +0/-0
Requirement of at least X levels in every class
« Reply #2 on: November 22, 2014, 09:50:28 am »


               

You can have both Harper and PDK levels.

Anyway, I'll see if it works. '<img'>



               
               

               
            

Legacy_Grani

  • Hero Member
  • *****
  • Posts: 1040
  • Karma: +0/-0
Requirement of at least X levels in every class
« Reply #3 on: November 24, 2014, 06:00:38 pm »


               

Alright, while the script Lightfoot8 provided wasn't exactly what I needed (for example, it didn't account for a player having both Harper and PDK levels) it gave me some ideas on how to improve my own.


Besides, I've analyzed it thoroughly and found out a lot of mistakes and unnecessities. I guess I should not write functions when it's that later already...


 


Anyway, here is a fixed version, which works exactly as I wanted it to work, as far as I've tested. I leave it here in case anyone wants to search after more bugs. Plus, someone might find it useful.



// Enforce that the PC will have at least a given number of levels in every
// class by the time he/she reaches the maximum level allowed in a module.
// If a PC gains a level that would make the above impossible,
// the level-up is is cancelled.
// Use at the beginning of an OnLevelUp script.
// - oPC: the levelling player
// - nMinLevel: the minimum number of levels in every class
// - nPossibleLevel: maximum character level allowed in a module
void EnforceAllowedLevel(object oPC, int nMinLevel, int nPossibleLevel = 40);

void EnforceAllowedLevel(object oPC, int nMinLevel, int nPossibleLevel = 40)
{
    //Declare variables
    int nClass2 = CLASS_TYPE_INVALID;
    int nClass3 = CLASS_TYPE_INVALID;
    int nClass1Levels;
    int nClass2Levels;
    int nClass3Levels;
    int nMinLevelC2;
    int nMinLevelC3;
    int nHD = GetHitDice(oPC);

    //Store PC's classes as variables (in case one of them is a Harper or a Knight; for this reason, only slots 2 and 3 are needed)
    nClass2 = GetClassByPosition(2, oPC);
    nClass3 = GetClassByPosition(3, oPC);

    //Store levels in each of the PC's class as variables
    nClass1Levels = GetLevelByPosition(1, oPC);
    nClass2Levels = GetLevelByPosition(2, oPC);
    nClass3Levels = GetLevelByPosition(3, oPC);

    //A special case - if nMinLevel is greater than 5, allow PCs to have only 5 levels of a Knight or/and a Harper class anyway
    nMinLevelC2 = nMinLevel;
    nMinLevelC3 = nMinLevel;
    if (nMinLevel > 5)
        {
            if (nClass2 == CLASS_TYPE_HARPER || nClass2 == CLASS_TYPE_PURPLE_DRAGON_KNIGHT) nMinLevelC2 = 5;
            if (nClass3 == CLASS_TYPE_HARPER || nClass3 == CLASS_TYPE_PURPLE_DRAGON_KNIGHT) nMinLevelC3 = 5;

        }

    //Accept the level-up if the PC doesn't multiclass and hasn't crossed a limit of the maximum possible level in a module
    if (nClass2 == CLASS_TYPE_INVALID)
        {
        if (nHD <= nPossibleLevel) return;
        }

    //Determine if the PC is allowed this level-up if the PC has 2 or 3 classes
    else
        {
            if (nClass1Levels < nMinLevel) nClass1Levels = nMinLevel;
            if (nClass2Levels < nMinLevel && nClass2 != CLASS_TYPE_INVALID) nClass2Levels = nMinLevelC2;
            if (nClass3Levels < nMinLevel && nClass3 != CLASS_TYPE_INVALID) nClass3Levels = nMinLevelC3;

            if (nClass1Levels + nClass2Levels + nClass3Levels <= nPossibleLevel) return;
        }

    //Cancel the level-up if need be
    int nXP = GetXP(oPC);
    int nExpMultiplier = nHD-1;
    SetXP(oPC, (nExpMultiplier*nExpMultiplier-nExpMultiplier)*500);
    DelayCommand(3.0, SetXP(oPC, nXP));
    FloatingTextStringOnCreature("You can't level in this class anymore!", oPC, TRUE);

}