• New Horizons on Maelstrom
    Maelstrom New Horizons


    Visit our website www.piratehorizons.com to quickly find download links for the newest versions of our New Horizons mods Beyond New Horizons and Maelstrom New Horizons!

Fixed Bug with skill boost items that require multiple of the item to work

Tingyun

Corsair
Storm Modder
Thank you Pieter for sharing the item skill bonus location in the your response other thread. By analyzing it, I was able to figure out that there is a bug with skill boost items that require multiple of the item to work.

Specifically, it seems that if an item requires a certain number of duplicates to give its skill bonus, if you have twice the required number the skill boost turns off. So if the item turns on when you have X, it turns off when you have 2X.

So, in the saved game I attached to my other thread (here is the link: Questions from the current build 4.1 of July | PiratesAhoy!)

Currently I have in my inventory 5 garnet and 6 pyrite, which should be granting bonuses to accuracy and cannons. Garnet requires 2 for the bonus, pyrite requires 3.

No bonuses are given to my character despite having the number.

It looks like:

If I give 2 garnet to my officer Gentile, both she and I get the bonus to that skill. I would then drop from 5 garnet to 3, meaning I have dropped below twice the requirement number of 2, and only then do I get the bonus.

If I give 1 pyrite to Gentile, I get the bonus, because I now have 5 pyrite, and the requirement is 3, so I am once again below 2X.

I am curious whether 3X the number would turn the boost back on, but I don't have enough of the substances involved.
 
You can use the console to give you anything you need for testing.
Would indeed be interesting to know.

Thanks for the report. I'm not sure why this would happen, but hopefully it'll become apparent when we look at the relevant code later. :doff
 
here is the code which triggers it. Haven't looked at it yet, will do later:
Code:
int CalcSkillModifier(ref character, string skillName)
{
    int j, qty;
    int mod = 0;
    ref itm;

    int iChrCabin = FindCharacterShipCabin(character); // KK
    for(j = 0; j < SKILLITEMS_QUANTITY; j++)
    {
        itm = &Items[NativeFindCharacter(&Items, SkillItems[j].id)];
        if(!CheckAttribute(itm, "skill." + skillName))
            continue;
// KK -->

        string itmid = itm.id;
        qty = GetCharacterItem(character, itmid);

        if (iChrCabin >= 0 && CheckAttribute(&Locations[iChrCabin], "box1.items." + itmid) == true)
            qty += sti(Locations[iChrCabin].box1.items.(itmid));
// <-- KK
        if( qty >= sti(itm.skill.num)) // *.skill.num = num required for effect. Default = 1
        {
            if(CheckAttribute(itm, "groupID") && IsCanEquiping(character, itm.groupID) && !IsEquipCharacterByItem(character, itmid))
                continue; // if equipable and not equipped, skip // KK

            // *.stack = num of item that can be stacked together. Default = 1
            if(sti(itm.skill.stack) >= qty/sti(itm.skill.num))
            {
                mod += sti(itm.skill.(skillName)) * qty/sti(itm.skill.num);
            }
            else
            {
                mod += sti(itm.skill.(skillName)) * sti(itm.skill.stack) / sti(itm.skill.num);
            }
        }
    }
    mod = iclamp(-MAX_SKILL_INCREASE, MAX_SKILL_INCREASE, mod); // PB: Single line
    character.skill.(skillName).modifier = mod;
    return mod;
}
 
I made some quick tests:

The problem is there already in stock POTC.
Testing mineral1 (pyrite 3 needed): any number >= 6 means no bonus. (not even 9)
 
okay let's see what happens then....

Code:
int CalcSkillModifier(ref character, string skillName)
{
    int j, qty;
    int mod = 0;
    ref itm;

    int iChrCabin = FindCharacterShipCabin(character); // KK
    for(j = 0; j < SKILLITEMS_QUANTITY; j++)
    {
        itm = &Items[NativeFindCharacter(&Items, SkillItems[j].id)];
        if(!CheckAttribute(itm, "skill." + skillName))
            continue;
// KK -->

        string itmid = itm.id;
        qty = GetCharacterItem(character, itmid);

        if (iChrCabin >= 0 && CheckAttribute(&Locations[iChrCabin], "box1.items." + itmid) == true)
            qty += sti(Locations[iChrCabin].box1.items.(itmid));
// <-- KK
The quantitiy is counted. we say its 8, so from now variable qty is 8.
Also the itm.skill.num is 3 as specified by @Jack Rackham , so we replace this in the following code too.
From the init items I see the itm.skill.stack is 1 so this can be replaced too.
And for the right skillname it should provide +1 for itm.skill.(skillName) so let's replace that too.
The variable MAX_SKILL_INCREASE is set to 4 on default so we assume it's this too.

Code:
        if( 8 >= 3) // *.skill.num = num required for effect. Default = 1
        {
            if(CheckAttribute(itm, "groupID") && IsCanEquiping(character, itm.groupID) && !IsEquipCharacterByItem(character, itmid))
                continue; // if equipable and not equipped, skip // KK
The if statement returned true so we are in the statement. the item is non-equipable so the next statement is of no concern.

Code:
            // *.stack = num of item that can be stacked together. Default = 1
            if(1 >= 8/3)
            {
                mod += 1 * 8/3;
            }
            else
            {
                mod += 1 * 1 / 3;
            }
The if statement gave false because 1 is not larger then 8/3 so we went into the else statement.
From here we can say that mod is equal to 1*1/3 which is 0.3333 with mod being a int this will be rounded down to be 0.

Code:
        }
    }
    mod = iclamp(-4, 4, mod); // PB: Single line
    character.skill.(skillName).modifier = mod;
    return mod;
}
so after this mod is still 0 and the modifier is 0, so the code is actually doing as it says it does. Now let's see what we want to happen, let's see what happens if the quantity is 5.

Code:
            // *.stack = num of item that can be stacked together. Default = 1
            if(1 >= 5/3)
            {
                mod += 1 * 5/3;
            }
            else
            {
                mod += 1 * 1 / 3;
            }
Now here does something strange happens. because you'd expect the game to still go into the else statement because 5/3 is larger then 1 but remember we are talking about ints here so the game will divide the two ints and store its value again in an int. It doesn't use a round funtion but just cuts off the fraction, so it says:
if(1 >= 1)
which is true, so here the game goes into the first statement and it says the mod is 1 because its 1 * 1 (again the ints). so thats why it does work here.

so here is the explanation of the problem. Now lets think about how to solve it. I will think about that a bit longer.
 
I don't see why the stack is actually needed in the code at all.
I would sugest to change this:
Code:
if(sti(itm.skill.stack) >= qty/sti(itm.skill.num))
            {
                mod += sti(itm.skill.(skillName)) * qty/sti(itm.skill.num);
            }
            else
            {
                mod += sti(itm.skill.(skillName)) * sti(itm.skill.stack) / sti(itm.skill.num);
            }
to this:

Code:
if(qty >= sti(itm.skill.num))
            {
                mod += sti(itm.skill.(skillName)) * qty/sti(itm.skill.num);
            }
this would keep mod 0 if qty is 0,1 or 2.
if qty is 3 it would set mod to 1
This would also happen with 4 an 5. it it's 6 the mod would become 2.
 
Here is a file with the change I sugested.
Place it in:
\PROGRAM\characters\skills

contained error
 
Last edited:
Stock PotC did not have item skill bonuses. ;)

I see a value being divided by an integer; that could be the reason.
In that "stack" section, try replacing sti with stf and see if that goes any better.
We've had some weird and annoying issues due to that before.

I didn't read everything above, so maybe @Levis already caught this.
 
Also, to clarify, stack IS needed to prevent items taking effect UNLESS you have multiple of them.

Plus I reckon that if you need three and have six, the bonus should work only once, not twice.
It is too easy to get high skills through items as it is.
 
Also, to clarify, stack IS needed to prevent items taking effect UNLESS you have multiple of them.

Plus I reckon that if you need three and have six, the bonus should work only once, not twice.
It is too easy to get high skills through items as it is.
qty checks how many items you have already. stack just checks how many can be in 1 stack right?
 
No, "stack" is a boolean that tells the game whether multiple of the same item give repeated skill bonuses.
Example: The Albatross gives -1 Luck, but does not stack (if I recall). So if you have 10 of them, it is still only -1 Luck and not -10.
Compare to the Cursed Coins that do stack: If you have 10, then you do get -10 Luck.
 
No, "stack" is a boolean that tells the game whether multiple of the same item give repeated skill bonuses.
Example: The Albatross gives -1 Luck, but does not stack (if I recall). So if you have 10 of them, it is still only -1 Luck and not -10.
Compare to the Cursed Coins that do stack: If you have 10, then you do get -10 Luck.
in the init items stack is just the value of how many can stack in your inventory.
cursed coin has a stack value of 10
albatros has a stack of 0 (as all books do)
pyrite has a stack value of 1

So you say if the stack value is 0 it shouldn't stack the skillbonus either, and if the stack if 1 or higher it should stack it?
 
Cursed Coin had a stack value of 10? Really?
Sounds like a typo. Should probably be 1.

And indeed "stack" controls if carrying multiple of the same item also gives multiple skill bonuses.
"Num required" on the other hand means that you need several of that item before its skill bonus takes effect at all.
 
Cursed Coin had a stack value of 10? Really?
Sounds like a typo. Should probably be 1.

And indeed "stack" controls if carrying multiple of the same item also gives multiple skill bonuses.
"Num required" on the other hand means that you need several of that item before its skill bonus takes effect at all.
shouldn't the cursded coin have a stack value of 882 ?

So if stack is 0 it shouldn't stack the skill bonus and if stack if 1 or higher it should stack the bonusses?
 
If "stack" were an integer indicating the maximum number of items that can have a skill effect, then perhaps. But that's not what "stack" does.
Even if it did do that, any number greater than 10 would be meaningless as you never get more than that in any skill anyway.
 
If "stack" were an integer indicating the maximum number of items that can have a skill effect, then perhaps. But that's not what "stack" does.
Even if it did do that, any number greater than 10 would be meaningless as you never get more than that in any skill anyway.
stack also means how many stack in your inventory right? Or did I understand it wrong? i guess 0 means the same as 1 in this case, every item will appear as a single item in your inventory. but if stack is 10 they will be grouped in groups of 10 right?
if you need to collect cursed coins you don't want the cursed coins to appear in your inventory all seperatly
 
No, it has nothing to do with that.
If you have multiple of the same item, they're always shown as one but with a number indicating their quantity.
Items never show separately in the Inventory unless they have a different ID.
 
No, it has nothing to do with that.
If you have multiple of the same item, they're always shown as one but with a number indicating their quantity.
Items never show separately in the Inventory unless they have a different ID.
really? I must have understood the stack wrong all this time then XD. might need to change some other items also then :p.
In that case the max skill mult is 4 so I guess any number above 4 doesn't matter.
Will look at it again and probably post another fix later today.
 
Indeed combined skill modifiers exceeding 4 don't do anything.
This is for balancing reasons.
 
I sugest to change this:
Code:
if(sti(itm.skill.stack) >= qty/sti(itm.skill.num))
            {
                mod += sti(itm.skill.(skillName)) * qty/sti(itm.skill.num);
            }
            else
            {
                mod += sti(itm.skill.(skillName)) * sti(itm.skill.stack) / sti(itm.skill.num);
            }
to this:

Code:
//Levis --> Changed to make stack independed and fix problem with the if statement
            //Check if the player has enough items
            if(qty >= sti(itm.skill.num))
            {
                //Check if the item bonuses stack
                if(sti(itm.skill.stack) > 0)
                {
                    //Check if the bonuses exceed the stack
                    if(sti(itm.skill.stack) >= qty/sti(itm.skill.num))
                    {
                        //they don't exceed the stack so apply the bonus.
                        mod += sti(itm.skill.(skillName)) * qty/sti(itm.skill.num);
                    }
                    else
                    {
                        //they do exceed the stack so apply the stack amount instead because it can't go higher
                        mod += sti(itm.skill.stack);
                    }
                }
                else
                {
                    //the items don't stack so it will only apply the bonus once
                    mod += sti(itm.skill.(skillName));
                }
            }
            //Levis <--

included is a file.
Please place it in:
\PROGRAM\characters\skills

see next page for right solution
 
Last edited:
Back
Top