Maximum Spell Points

Discuss IB/IBx engine ideas, bugs, etc.
Post Reply
User avatar
Dorateen
Posts: 316
Joined: Thu Jan 16, 2020 3:03 pm

Maximum Spell Points

Post by Dorateen »

Today I learned that the maximum spell points for a character is capped at 300. At least, I think that is what happened, when I tried to equip an item that would push the spell points over 300, and it not work. But it did give the new spell points to another character who had a lower total.

Is there a place to see if stats like hit points and spell points have a limit, and if that data can be changed? I don't mind the 300 cap. But I'm more concerned what will happen if a wizard trains to a high level and the 20 additional sp would exceed that number.

edit: Upon further investigation, it could be that the character had a custom trait, which already increased max sp and that was overriding any gain from an item. Still it would be interesting to know if there is any data that could put a cap on the number.
User avatar
slowdive
Site Admin
Posts: 509
Joined: Wed Jan 15, 2020 4:37 am

Re: Maximum Spell Points

Post by slowdive »

I am not aware of any cap on SP or HP. I'll have to dig into it a bit to see if there is anywhere in the code that may have caused this.

EDIT: after looking at the most probably code that would set the MaxSp, it seems that there could be some interactions with item effects or trait effects. I also see some possible duplication of trait bonuses since the two subroutines seem to look at pc.effectList for bonuses.

Code: Select all

int iMod = modifierFromSPRelevantAttribute;
pc.spMax = pc.playerClass.startingSP + iMod + ((pc.classLevel - 1) * (pc.playerClass.spPerLevelUp + iMod)) + CalcAttributeModifierSpMax(pc) + CalcModifierMaxSP(pc);            

Code: Select all

public int CalcAttributeModifierSpMax(Player pc)
        {
            int spMaxBonuses = 0;            
            int highestNonStackable = -99;
            foreach (Effect ef in pc.effectsList)
            {
                if (isPassiveTraitApplied(ef, pc))
                {
                    if (ef.isStackableEffect)
                    {
                        spMaxBonuses += ef.modifySpMax;
                    }
                    else
                    {
                        if ((ef.modifySpMax != 0) && (ef.modifySpMax > highestNonStackable))
                        {
                            highestNonStackable = ef.modifySpMax;
                        }
                    }
                }
            }
            if (highestNonStackable > spMaxBonuses) { spMaxBonuses = highestNonStackable; }
            return spMaxBonuses;
        }

Code: Select all

public int CalcModifierMaxSP(Player pc)
        {
            int attBonuses = 0;
            attBonuses += mod.getItemByResRefForInfo(pc.BodyRefs.resref).modifierMaxSP;
            attBonuses += mod.getItemByResRefForInfo(pc.MainHandRefs.resref).modifierMaxSP;
            attBonuses += mod.getItemByResRefForInfo(pc.OffHandRefs.resref).modifierMaxSP;
            attBonuses += mod.getItemByResRefForInfo(pc.RingRefs.resref).modifierMaxSP;
            attBonuses += mod.getItemByResRefForInfo(pc.HeadRefs.resref).modifierMaxSP;
            attBonuses += mod.getItemByResRefForInfo(pc.GlovesRefs.resref).modifierMaxSP;
            attBonuses += mod.getItemByResRefForInfo(pc.NeckRefs.resref).modifierMaxSP;
            attBonuses += mod.getItemByResRefForInfo(pc.Ring2Refs.resref).modifierMaxSP;
            attBonuses += mod.getItemByResRefForInfo(pc.FeetRefs.resref).modifierMaxSP;
            int highestNonStackable = -99;
            foreach (Effect ef in pc.effectsList)
            {
                if (isPassiveTraitApplied(ef, pc))
                {
                    if (ef.isStackableEffect)
                    {
                        attBonuses += ef.modifySpMax;
                    }
                    else
                    {
                        if ((ef.modifySpMax != 0) && (ef.modifySpMax > highestNonStackable))
                        {
                            highestNonStackable = ef.modifySpMax;
                        }
                    }
                }
            }
            if (highestNonStackable > -99) { attBonuses = highestNonStackable; }
            return attBonuses;
        }
User avatar
Dorateen
Posts: 316
Joined: Thu Jan 16, 2020 3:03 pm

Re: Maximum Spell Points

Post by Dorateen »

Right, there probably isn't. The character has 283 spell points, and the equipped item would have pushed him over 300. When the additional sp were not gained, the first thought I had was it must be capped. But it's likely a conflict with the trait.
User avatar
slowdive
Site Admin
Posts: 509
Joined: Wed Jan 15, 2020 4:37 am

Re: Maximum Spell Points

Post by slowdive »

I'll need to review the two routines a bit and see if I am missing something, but my initial thought is that passive traits could be double counted. It looks like one of the two routines looks at bonuses from equipped items and taits and the other just looks at traits (but they get added together so could double the trait bonus):

Karl worked on this one, so I'll need to wrap my head around it first before changing anything.

Code: Select all

public bool isPassiveTraitApplied(Effect ef, Player pc)
        {
            //code block for cheking tag based trait requirements

            //we have an effect coming from a passive trait
            //for non permanent effects fed to it the method returns true in any case
            if (ef.isPermanent)
            {//1
                bool traitWorksForThisPC = false;

                // set up effects lists for traitWorksOnlyWhen and traitWorksNeverWhen
                ef.traitWorksNeverWhen.Clear();
                ef.traitWorksOnlyWhen.Clear();
                //go through all trait tags of pc
                foreach (string traitTag in pc.knownTraitsTags)
                {//2
                 //go through all traits of module
                    foreach (Trait t in gv.mod.moduleTraitsList)
                    {//3
                     //found a trait the pc has
                        if (t.tag.Equals(traitTag))
                        {//4
                         //go through effect tags for drop down list of this trait
                            foreach (EffectTagForDropDownList effectTag in t.traitEffectTagList)
                            {//5
                             //found out that our current effect ef stems from this trait of the pc
                                if (effectTag.tag.Equals(ef.tag))
                                {//6
                                 //built the lists on runtime for our current ef from the trait's template
                                    foreach (LocalImmunityString ls in t.traitWorksOnlyWhen)
                                    {//7
                                        LocalImmunityString ls2 = ls.DeepCopy();
                                        ef.traitWorksOnlyWhen.Add(ls2);
                                    }//7closed

                                    foreach (LocalImmunityString ls in t.traitWorksNeverWhen)
                                    {//7
                                        LocalImmunityString ls2 = ls.DeepCopy();
                                        ef.traitWorksNeverWhen.Add(ls2);
                                    }//7closed

                                    //ef.traitWorksNeverWhen = t.traitWorksNeverWhen;
                                    //ef.traitWorksOnlyWhen = t.traitWorksOnlyWhen;
                                }//6closed
                            }//5 closed
                        }//4closed
                    }//3closed
                }//2clsoed

                if (ef.traitWorksOnlyWhen.Count <= 0)
                {
                    traitWorksForThisPC = true;
                }

                //note that the tratNeccessities are logically connected with OR the way it is setup
                else
                    foreach (LocalImmunityString traitNeccessity in ef.traitWorksOnlyWhen)
                    {
                        foreach (string pcTag in pc.pcTags)
                        {
                            if (traitNeccessity.Value.Equals(pcTag))
                            {
                                traitWorksForThisPC = true;
                                break;
                            }
                        }
                    }

                //one redFlag is enough to stop the trait from working, ie connected with OR, too
                if (traitWorksForThisPC)
                {
                    foreach (LocalImmunityString traitRedFlag in ef.traitWorksNeverWhen)
                    {
                        foreach (string pcTag in pc.pcTags)
                        {
                            if (traitRedFlag.Value.Equals(pcTag))
                            {
                                traitWorksForThisPC = false;
                                break;
                            }
                        }
                    }
                }
                //note: work with  if (traitWorksForThisPC){} from here on

                if (traitWorksForThisPC)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                return true;
            }
        }
User avatar
Dorateen
Posts: 316
Joined: Thu Jan 16, 2020 3:03 pm

Re: Maximum Spell Points

Post by Dorateen »

slowdive wrote: Fri Oct 01, 2021 7:26 pm , but my initial thought is that passive traits could be double counted. It looks like one of the two routines looks at bonuses from equipped items and taits and the other just looks at traits (but they get added together so could double the trait bonus)
You are absolutely right. I just looked at the spell points calculation for a 9th level wizard:

20 sp per level = 180

25 intelligence gives 7 sp per level = 63

The trait is supposed to increase the max sp by 20. That would bring the total up to 263.

But the trait is double counted, bringing the total up to 283 instead.
User avatar
slowdive
Site Admin
Posts: 509
Joined: Wed Jan 15, 2020 4:37 am

Re: Maximum Spell Points

Post by slowdive »

The above routines check for stackable trait effects to stack, but for non-stackable, it uses the highest value. It also looks like the item bonuses stack, but they are then compared to the highest non-stackable trait effect and the higher value gets used. This needs to be fixed so that the item values do not get replaced and instead will stack on top of the trait value (either highest of stackable trait values or highest non-stackable trait value, whichever is higher).
Post Reply