1. Dismiss Notice
  2. GOG.com logo

    Thanks to YOUR votes, GOG.com now sells:
    - Sea Dogs - Sea Dogs: Caribbean Tales
    - Sea Dogs: City of Abandoned Ships

    Vote now to add Pirates of the Caribbean to the list!

    Dismiss Notice
  3. Under the Crossbones Podcast

    A Pirate Podcast with Interviews
    Music, Comedy and all things Pirate!

    - Episode Guide - About - Subscribe -
    - Twitter - Facebook - iTunes - Android -
    - Youtube - Fill the Coffers -

    Dismiss Notice
  4. New Horizons logo

    Quick links for PotC: New Horizons
    - Download latest version
    - Wiki - FAQ - Report bugs here
    - ModDB profile

  5. GOF logo

    Quick links for AoP2: Gentlemen of Fortune 2
    - Downloads and info
    - Historical Immersion Supermod
    - ModDB Profile

Dismiss Notice
New to the forum?
Please take a moment to read our Welcome Message and Forum Rules.

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

Discussion in 'Bug Archive' started by Tingyun, Aug 16, 2016.

  1. Tingyun

    Tingyun Corsair Storm Modder

    Joined:
    Aug 8, 2016
    Messages:
    1,445
    Gender:
    Male
    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.
     
  2. Pieter Boelen

    Pieter Boelen (Not So) Old Seadog Staff Member Administrator Storm Modder Hearts of Oak Donator

    Joined:
    Nov 11, 2004
    Messages:
    66,581
    Gender:
    Male
    Occupation:
    Maritime Research: Project Engineer (Analysis)
    Location:
    Wageningen, The Netherlands
    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
     
  3. Levis

    Levis Find(Rum) = false; Staff Member Programmer Creative Support Storm Modder

    Joined:
    Oct 6, 2013
    Messages:
    6,683
    Gender:
    Male
    Occupation:
    ICT
    Location:
    University Twente (Netherlands)
    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;
    }
    
     
  4. Jack Rackham

    Jack Rackham HoO Team Member Quest Writer Storm Modder

    Joined:
    Jul 5, 2004
    Messages:
    3,287
    Gender:
    Male
    Occupation:
    math teacher
    Location:
    Sund, Ramsjö, Sweden
    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)
     
  5. Levis

    Levis Find(Rum) = false; Staff Member Programmer Creative Support Storm Modder

    Joined:
    Oct 6, 2013
    Messages:
    6,683
    Gender:
    Male
    Occupation:
    ICT
    Location:
    University Twente (Netherlands)
    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.
     
  6. Levis

    Levis Find(Rum) = false; Staff Member Programmer Creative Support Storm Modder

    Joined:
    Oct 6, 2013
    Messages:
    6,683
    Gender:
    Male
    Occupation:
    ICT
    Location:
    University Twente (Netherlands)
    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.
     
  7. Levis

    Levis Find(Rum) = false; Staff Member Programmer Creative Support Storm Modder

    Joined:
    Oct 6, 2013
    Messages:
    6,683
    Gender:
    Male
    Occupation:
    ICT
    Location:
    University Twente (Netherlands)
    Here is a file with the change I sugested.
    Place it in:
    \PROGRAM\characters\skills

    contained error
     
    Last edited: Aug 17, 2016
  8. Pieter Boelen

    Pieter Boelen (Not So) Old Seadog Staff Member Administrator Storm Modder Hearts of Oak Donator

    Joined:
    Nov 11, 2004
    Messages:
    66,581
    Gender:
    Male
    Occupation:
    Maritime Research: Project Engineer (Analysis)
    Location:
    Wageningen, The Netherlands
    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.
     
  9. Pieter Boelen

    Pieter Boelen (Not So) Old Seadog Staff Member Administrator Storm Modder Hearts of Oak Donator

    Joined:
    Nov 11, 2004
    Messages:
    66,581
    Gender:
    Male
    Occupation:
    Maritime Research: Project Engineer (Analysis)
    Location:
    Wageningen, The Netherlands
    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.
     
  10. Levis

    Levis Find(Rum) = false; Staff Member Programmer Creative Support Storm Modder

    Joined:
    Oct 6, 2013
    Messages:
    6,683
    Gender:
    Male
    Occupation:
    ICT
    Location:
    University Twente (Netherlands)
    qty checks how many items you have already. stack just checks how many can be in 1 stack right?
     
  11. Pieter Boelen

    Pieter Boelen (Not So) Old Seadog Staff Member Administrator Storm Modder Hearts of Oak Donator

    Joined:
    Nov 11, 2004
    Messages:
    66,581
    Gender:
    Male
    Occupation:
    Maritime Research: Project Engineer (Analysis)
    Location:
    Wageningen, The Netherlands
    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.
     
  12. Levis

    Levis Find(Rum) = false; Staff Member Programmer Creative Support Storm Modder

    Joined:
    Oct 6, 2013
    Messages:
    6,683
    Gender:
    Male
    Occupation:
    ICT
    Location:
    University Twente (Netherlands)
    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?
     
  13. Pieter Boelen

    Pieter Boelen (Not So) Old Seadog Staff Member Administrator Storm Modder Hearts of Oak Donator

    Joined:
    Nov 11, 2004
    Messages:
    66,581
    Gender:
    Male
    Occupation:
    Maritime Research: Project Engineer (Analysis)
    Location:
    Wageningen, The Netherlands
    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.
     
  14. Levis

    Levis Find(Rum) = false; Staff Member Programmer Creative Support Storm Modder

    Joined:
    Oct 6, 2013
    Messages:
    6,683
    Gender:
    Male
    Occupation:
    ICT
    Location:
    University Twente (Netherlands)
    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?
     
  15. Pieter Boelen

    Pieter Boelen (Not So) Old Seadog Staff Member Administrator Storm Modder Hearts of Oak Donator

    Joined:
    Nov 11, 2004
    Messages:
    66,581
    Gender:
    Male
    Occupation:
    Maritime Research: Project Engineer (Analysis)
    Location:
    Wageningen, The Netherlands
    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.
     
  16. Levis

    Levis Find(Rum) = false; Staff Member Programmer Creative Support Storm Modder

    Joined:
    Oct 6, 2013
    Messages:
    6,683
    Gender:
    Male
    Occupation:
    ICT
    Location:
    University Twente (Netherlands)
    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
     
  17. Pieter Boelen

    Pieter Boelen (Not So) Old Seadog Staff Member Administrator Storm Modder Hearts of Oak Donator

    Joined:
    Nov 11, 2004
    Messages:
    66,581
    Gender:
    Male
    Occupation:
    Maritime Research: Project Engineer (Analysis)
    Location:
    Wageningen, The Netherlands
    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.
     
  18. Levis

    Levis Find(Rum) = false; Staff Member Programmer Creative Support Storm Modder

    Joined:
    Oct 6, 2013
    Messages:
    6,683
    Gender:
    Male
    Occupation:
    ICT
    Location:
    University Twente (Netherlands)
    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.
     
  19. Pieter Boelen

    Pieter Boelen (Not So) Old Seadog Staff Member Administrator Storm Modder Hearts of Oak Donator

    Joined:
    Nov 11, 2004
    Messages:
    66,581
    Gender:
    Male
    Occupation:
    Maritime Research: Project Engineer (Analysis)
    Location:
    Wageningen, The Netherlands
    Indeed combined skill modifiers exceeding 4 don't do anything.
    This is for balancing reasons.
     
  20. Levis

    Levis Find(Rum) = false; Staff Member Programmer Creative Support Storm Modder

    Joined:
    Oct 6, 2013
    Messages:
    6,683
    Gender:
    Male
    Occupation:
    ICT
    Location:
    University Twente (Netherlands)
    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: Aug 17, 2016

Share This Page