• 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 Sails repairing up to 100% is impossible!

Hi!
I hope you can understand me, because i am not a native english speaker ....

i have the same problem you have in GoF 2 (last patch). For all ships with more than 100 Sail Health Points you cannot repair the sail to 100% by you own reapir (only at shipyard).
After looking at all the code lines, i think i know where that problem comes from (the original code was only writen for 100 Sail HP, so there was never a difference in Sail HPs and percent).

All first codes are in Program/characters/CharacterUtilite

GetSailPercent
-> get the percent of the actual sail (actual SP / max SP * 100)

GetSailRPD (i think RPD = Repair Per Day)
-> value in percent (depends on skills)

GetSailSPP (SPP = Sailcloth Per Percent)
-> value of goods need for repair Per 1% (depends on Builder perk and ship class)

GetSailRepairDay
now all these values get loaded:
-> repPercent (Repair per Day in percent)
-> matQ (needed material)
-> tmpf (check if and how many sailcoth are on ship)
after that there is a check if there are enough goods for the full sail repair per day
then there is "return repPercent;"

if you look now at Program/battle_interface/BattleInterface
you find that in ProcessDayReapair there are the above listed commands and a new one: ProcessSailRepair

That one is writen in Program battle_interface/utils
in ProcessSailRepair there is a long code about checking if mast is down or not
and then every single sail get repaired by "OneSailDmgRepair" (one by one)

and know there is the actual repair with "OneSailDmgRepair":
1. there is a check if that special sail is damaged
2. check if more repair value than damage -> full repair of that special sail and return that repaired value (because the complete repair value get reduced by it and then next sail get checked)
3. if less repair value than damage, use it to repair sail, then stop

and somewhere in these two commands there is the main problem:
all single sails (they have sail health points) together get repaired by A PERCENT VALUE, but they should get repaired by:
(max Sail Health Points) * (repair value in Percent) / 100
(sail with refShip.SP = 500 get repaired with +5, not with +5% with is( 5% of 500) + 25)

i try to figure out where i can modify "OneSailDmgRepair" or "ProcessSailRepair" to actual repair the right amount of sail
i look at the value: fMakeRepair (in ProcessSailRepair)
float fMakeRepair = repPercent; -> is the amount of repair as a whole(the amount of repair points needed for repairing a single sail get subtract from this value), but in this code line it is a percent value (in original AoP COAS all ships have sail health points of 100 (ships_init, refShip.SP=100), so there was no difference between a percent value and the actual amount of Sail Health Points repaired per day
a possible solution is to modify this point so it becomes the real value:
IDEA: float fMakeRepair = repPercent * (refShip.SP) / 100

idea for changing the actual code: (same fSP as in GetSailPercent in CharacterUtilite)
float fSP = GetCharacterShipSP(chref);
float fMakeRepair = repPercent * fSP / 100

perhaps all my looking at this problem is wrong or useless,or i try to modify the code at the wrong position,
but there is a similar line in the command ProcessHullRepair (but there is no need for checking for falling mast and repair things (sails) one by one so it is much easier to understand)

float ProcessHullRepair(ref chref,float repPercent)
{
float dmg = 100.0 - GetHullPercent(chref);
if(dmg==0.0) return 0.0;
if(repPercent>dmg) repPercent=dmg;
int blotsQuantity = GetBlotsQuantity(chref);
int repBlots = makeint(blotsQuantity*repPercent/dmg);
DeleteBlots(chref,repBlots);
float baseHP = makefloat(GetCharacterShipHP(chref));
chref.ship.HP = baseHP+(repPercent-dmg)*baseHP/100.0;

if(sti(chref.ship.HP) > baseHP)
{
chref.ship.HP = baseHP;
}
return repPercent;
}



By the way, if you want to talk about this idea, you can PM me a skype or TS3 address and we can perhaps talk better about it!
 
Last edited:
Ahoy, @PaterBrown ! I'm not a native English speaker too and i understand your English, but, unfortunately, not what do you mean.
After looking at all the code lines, i think i know where that problem comes from (the original code was only writen for 100 Sail HP, so there was never a difference in Sail HPs and percent).
My ship's current SP (_refCharacter.Ship.SP) = 197.3393097.
My ship's max SP (GetCharacterShipSP) = 200.
So, GetSailPercent function returns value of 98.67, which is % 197.3393097 of 200:
Code:
float GetSailPercent(ref _refCharacter)
{
    if( !CheckAttribute(_refCharacter,"Ship.SP") ) return 100.0;
    int iSP = GetCharacterShipSP(_refCharacter);
    if(iSP<=0) return 100.0;
    float fpsp = 100.0*stf(_refCharacter.Ship.SP)/iSP;
    return fpsp;

AND NOW THE PROBLEM
lastline is "return repPercent"
but if a ship has more than 100 Sail Health Points, there should be

float fSP = GetCharacterShipSP(_refCharacter); (same line as in GetSailPercent, get max Sail Health Points)
repPercent = repPercent * fSP / 100;
return repPercent;
Which function do you mean?
 
sry, edited my post a bit, please take a new look!
i noticed i did not explain my ideas good...

specially the point where i should try to fix it was wrong in the first versions of my post
 
for me (GoF, not New Horizons) the modifyed ProcessSailRepair command loooks like this
red is changed

MAYBE it works, but can have side effect, see next posts
( i will still keep it here, so others can check what i tryed.....)

SEE MY LATER POST, CODE IS WORKING, BUG FIXED

Code:
float ProcessSailRepair(ref chref, float repPercent)
{
   float dmg = 100.0-GetSailPercent(chref);
   if(dmg==0.0) return 0.0;
   if(repPercent>dmg) repPercent=dmg;

                               //PaterBrown fix
   float fSP = GetCharacterShipSP(chref);           // new line
   float fMakeRepair = repPercent * fSP / 100       // old only        float fMakeRepair = repPercent;                        

   int i,j,rq,gq;
   aref arRoot,arGroup,arSail;
   string tmpstr;
   makearef(arRoot, chref.ship.sails);
   rq = GetAttributesNum(arRoot);
 
   for(i=0; i<rq; i++)
   {
       arGroup = GetAttributeN(arRoot, i);
       gq = GetAttributesNum(arGroup);
       for(j=0; j<gq; j++)
       {
           arSail = GetAttributeN(arGroup, j);
      
           if( CheckAttribute(arSail,"mastFall") )
           {
               tmpstr = "ship.masts."+arSail.mastFall;
               if( CheckAttribute(chref,tmpstr) && stf(chref.(tmpstr))>=1.0 )   {continue;}
           }
           fMakeRepair -= OneSailDmgRepair(chref,arGroup,arSail,fMakeRepair);
           if(fMakeRepair<=0.0) {break;}
           if(!CheckAttribute(chref,"ship.sails")) break;
           if(GetAttributesNum(arRoot)!=rq) break;
           if(GetAttributesNum(arGroup)!=gq)
           {
               gq = GetAttributesNum(arGroup);
               j--;
           }
       }
       if(fMakeRepair<=0.0) {break;}
       if(!CheckAttribute(chref,"ship.sails")) break;
       if(GetAttributesNum(arRoot)!=rq)
       {
           rq = GetAttributesNum(arRoot);
           i--;
       }
   }
   chref.ship.sp = CalculateShipSP(chref);
   repPercent -= fMakeRepair;
   return repPercent;
}
 
Last edited:
i really dont know how to fix it, but the problem should be the value "fMakeRepair"
-> it is defined through a percent value
-> it is used a the whole amount of repair (which should the percent value multiplied with the base value)


i will try to explain the problem at a ship with SP = 500 and damaged to 495 points (99% sail left, 1% damage)

code should work like:
-> get damage percent : 1%
-> check repair per day (lets say as an example it is 3% , so it is enough)
-> check for enough sailcloth (for example: we need 5, we have 10, so it is enough)

now repair
-> 495 SP + (repair) 1 % (of 500 SP)
495 SP + 0,01 * 500 SP = 495 SP + 5 SP = 500 SP

-> Sail full repaired! (all fine)


repair code actually works like:
-> 495 + (repair) 1 (not percent of something)
495 SP + 1 SP = 496 SP

no full repair, and this is an infinitely repair process, we will get closer to 500 SP but we will never reach it
next day repair of 4 SP, which is 0,8%
-> 496,8 SP
next day repair of 3,2 SP, which is 0,64%
-> 497,44 SP
next day repair of 2,56 SP, which is 0,512 %
->497,952
next day repair of 2,048 SP, which is 0,4096%
-> 498,3616
... and so on
 
Why not? It must helps.
Code:
float ProcessSailRepair(ref chref, float repPercent)
{
    if (repPercent == 0.0) return 0.0;            // LDH out of sailcloth - 25Feb09
    float dmg = 100.0-GetSailPercent(chref);
    if(dmg==0.0) return 0.0;
    if(repPercent>dmg) repPercent=dmg;
    float maxShipSP = GetCharacterShipSP(chref); // new line
    float fMakeRepair = (repPercent * maxShipSP)/100; // new line, was float fMakeRepair = repPercent;
    int i,j,rq,gq;
    aref arRoot,arGroup,arSail;
    string tmpstr;
    makearef(arRoot, chref.ship.sails);
    rq = GetAttributesNum(arRoot);
...

With this changes i have reached 100 % in two days with 91% of sails condition on start.

Thank you, @PaterBrown, probably, it is a right way!

Try to reload the savegame and do it again.
 
Last edited:
that`s fine!!!
i could repair my sail to 100% with this change, too.
so this definitly removes the above described issue!
But for me the their was a strange change in the value "repair per day"
it was around 8% when sail was 91%
and dropped to around 6 % with sail at 86%
(i did not know what happened in the background, this were just the values shown ingame)
and i dont even know why and how ( and if that is connect to this fix)


and there is the question about the last lines of the command "ProcessSailRepair":

Code:
.......
}
chref.ship.sp = CalculateShipSP(chref);
repPercent -= fMakeRepair;
return repPercent;
}

there the changed value "fMakeRepair" get subtracted from repPercent (this can be a big problem)
before the fix "fMakeRepair" was always less than "repPercent" (because of the way it was defined and used)
now we cannot say that for sure, so the last line can return a negative value for "repPercent"
maybe we need to add an if command to be sure repPercent is bigger than zero

perhaps we need to change the end, too

Code:
float ProcessSailRepair(ref chref, float repPercent)
{
    if (repPercent == 0.0) return 0.0;            // LDH out of sailcloth - 25Feb09
    float dmg = 100.0-GetSailPercent(chref);
    if(dmg==0.0) return 0.0;
    if(repPercent>dmg) repPercent=dmg;
    float maxShipSP = GetCharacterShipSP(chref); // new line
    float fMakeRepair = (repPercent * maxShipSP)/100; // new line, was float fMakeRepair = repPercent;
    int i,j,rq,gq;
    aref arRoot,arGroup,arSail;
    string tmpstr;
    makearef(arRoot, chref.ship.sails);
    rq = GetAttributesNum(arRoot);

  ...

  }
  chref.ship.sp = CalculateShipSP(chref);
  fMakeRepair =( fMakeRepair / maxShipSP ) * 100;  //new line
  repPercent -= fMakeRepair;
if(repPercent<0)      //new line
 {repPercent=0;}      // new line
  return repPercent;
}

...
 
Last edited:
Yes, it will be right, but i have not this line (repPercent -= fMakeRepair;). My function looks like next:
Code:
float ProcessSailRepair(ref chref, float repPercent)
{
    if (repPercent == 0.0) return 0.0;            // LDH out of sailcloth - 25Feb09
    float dmg = 100.0-GetSailPercent(chref);
    if(dmg==0.0) return 0.0;
    if(repPercent>dmg) repPercent=dmg;
    float maxShipSP = GetCharacterShipSP(chref); //my
    float fMakeRepair = (repPercent * maxShipSP)/100; // was float fMakeRepair = repPercent;
    int i,j,rq,gq;
    aref arRoot,arGroup,arSail;
    string tmpstr;
    makearef(arRoot, chref.ship.sails);
    rq = GetAttributesNum(arRoot);
    for(i=0; i<rq; i++)
    {
        arGroup = GetAttributeN(arRoot, i);
        gq = GetAttributesNum(arGroup);
        for(j=0; j<gq; j++)
        {
            arSail = GetAttributeN(arGroup, j);
            if( CheckAttribute(arSail,"mastFall") )
            {
                tmpstr = "ship.masts."+arSail.mastFall;
                if( CheckAttribute(chref,tmpstr) && stf(chref.(tmpstr))>=1.0 )    {continue;}
            }
            fMakeRepair -= OneSailDmgRepair(chref,arGroup,arSail,fMakeRepair);
            if(fMakeRepair<=0.0) {break;}
            if(!CheckAttribute(chref,"ship.sails")) break;
            if(GetAttributesNum(arRoot)!=rq) break;
            if(GetAttributesNum(arGroup)!=gq)
            {
                gq = GetAttributesNum(arGroup);
                j--;
            }
        }
        if(fMakeRepair<=0.0) {break;}
        if(!CheckAttribute(chref,"ship.sails")) break;
        if(GetAttributesNum(arRoot)!=rq)
        {
            rq = GetAttributesNum(arRoot);
            i--;
        }
    }
    chref.ship.sp = CalculateShipSP(chref);    // Note: this is wrong for tutorial, damage isn't set correctly on tutorial ship - 25Feb09

    // LDH add repair skill for repairs - 21Jan09
    // This will add skill for repairs done at shipyard. This is intentional.
    if (AUTO_SKILL_SYSTEM)
    {
        if (sti(chref.index) == GetMainCharacterIndex())        // LDH 24Jan09
            Trace("Repair & Defence skill added in ProcessSailRepair: " + repPercent + " actual " + makeint(repPercent + 0.5));
        int AddSkill = makeint(repPercent + 0.5);  if (AddSkill < 20) AddSkill = 20;
        AddPartyExpChar(chref, "Repair", AddSkill));
        AddPartyExpChar(chref, "Defence", AddSkill);
    }

    return repPercent;
}
As for sailcloth quantity for repairing, it needs to verify.
 
ok, there might be some difference between GoF and New Horizons
for me, i tested it in battle, i was not firing and just let enemys shot me and damge sail (i wrote the values down on paper after each enemy firing at me)
SP Percent repairPercent sailcoth
250
241 96,5 3,54 12
233 93,3 6,69 24
219 87,9 5,04 18
216 86,5 4,52 16
214 85,7 4,28 15​
i really dont know how this happened, and even the repairing changes
224 89,9 6,02 21
240 (to full repair)​
it is so strange, i dont know how this fix can impact like that

i will delete "repPercent -= fMakeRepair;" and test it again

deleting changes nothing, going for a short break and a drink before next trys ;)
 
Last edited:
a drink always helps....
this strange behavior is because of the code in the function "GetSailRPD", so this behavior is intended and has nothing to do with this fix!

BUG SOLVED, CODE WORKING
for "New Horizons" look at Serge Grey bugfix
for "GoF" look at this one

command to fix is in Program/battle_interface/utils.c
Code:
float ProcessSailRepair(ref chref, float repPercent)
{
   float dmg = 100.0-GetSailPercent(chref);
   if(dmg==0.0) return 0.0;
   if(repPercent>dmg) repPercent=dmg;

       float maxShipSP = GetCharacterShipSP(chref);                          // new line by Serge Grey & PaterBrown
       float fMakeRepair = (repPercent * maxShipSP)/100;            // new line, was float fMakeRepair = repPercent;

   int i,j,rq,gq;
   aref arRoot,arGroup,arSail;
   string tmpstr;
   makearef(arRoot, chref.ship.sails);
   rq = GetAttributesNum(arRoot);

   for(i=0; i<rq; i++)
   {
       arGroup = GetAttributeN(arRoot, i);
       gq = GetAttributesNum(arGroup);
       for(j=0; j<gq; j++)
       {
           arSail = GetAttributeN(arGroup, j);
       
           if( CheckAttribute(arSail,"mastFall") )
           {
               tmpstr = "ship.masts."+arSail.mastFall;
               if( CheckAttribute(chref,tmpstr) && stf(chref.(tmpstr))>=1.0 )   {continue;}
           }
           fMakeRepair -= OneSailDmgRepair(chref,arGroup,arSail,fMakeRepair);
           if(fMakeRepair<=0.0) {break;}
           if(!CheckAttribute(chref,"ship.sails")) break;
           if(GetAttributesNum(arRoot)!=rq) break;
           if(GetAttributesNum(arGroup)!=gq)
           {
               gq = GetAttributesNum(arGroup);
               j--;
           }
       }
       if(fMakeRepair<=0.0) {break;}
       if(!CheckAttribute(chref,"ship.sails")) break;
       if(GetAttributesNum(arRoot)!=rq)
       {
           rq = GetAttributesNum(arRoot);
           i--;
       }
   }
   chref.ship.sp = CalculateShipSP(chref);


   return repPercent;
}

i hope they can use this bugfix in "New Horizons Remastered"
 
Take variables with and without changes.
My are:
repPercent=4.818
matQ = 14.454

They're same.
Probably it goes right.

going for a short break and a drink before next trys
Do you prefer rum? ;)

It's your achievement, mate. I did only what you clarified to me. Thank you.

Do not know what is a TEHO, but @LarryHookins had the close idea.
 
Last edited:
Do you prefer rum? ;)
of course, i am a pirate after all


the code in "GetSailRPD" looks like this (in GoF)
Code:
float GetSailRPD(ref _refCharacter) // ïðîöåíò ðåìîíòà ïàðóñîâ â äåíü
{
   float repairSkill = GetSummonSkillFromNameToOld(_refCharacter, SKILL_REPAIR);
   if(CheckOfficersPerk(_refCharacter, "Carpenter"))
   {
       repairSkill = repairSkill * 1.1;
   }
   float damagePercent = 100.0 - GetSailPercent(_refCharacter);
   if (damagePercent == 0.0) return 0.0;

   float ret = repairSkill*15.0 / damagePercent;
   if (ret > damagePercent) ret = damagePercent;
  
   return ret;  //boal
}

this (in my opnion strange) behavior is intended, of course i can change it by hand
but then i need to think how i want it .... because it is not that easy to balance...
with low skill you need at least 2% of repair (else you will never get exp to raise this skill)
with 100 repair skill you need maximum 20% (so it is still balanced)
decide if it should be linear or something else.....​
it is working, so why should i change it

we solved that "never repair to 100% bug" !
so let us set sail and plunder some merchants :ship
 
These games has different systems.
In my case defence skill increases too, but, for some reason, less, interesting why, there are the same lines:
Code:
// LDH add repair skill for repairs - 21Jan09
    // This will add skill for repairs done at shipyard. This is intentional.
    if (AUTO_SKILL_SYSTEM)
    {
        if (sti(chref.index) == GetMainCharacterIndex())        // LDH 24Jan09
            Trace("Repair & Defence skill added in ProcessSailRepair: " + repPercent + " actual " + makeint(repPercent + 0.5));
        int AddSkill = makeint(repPercent + 0.5);  if (AddSkill < 20) AddSkill = 20;
        AddPartyExpChar(chref, "Repair", AddSkill));
        AddPartyExpChar(chref, "Defence", AddSkill);
    }

repair 53 -> 57
defence 40 -> 41

In line AddPartyExpChar(chref, "Repair", AddSkill)); ")" is excessive. There is the same in ProcessHullRepair. Strange, game works with them without error.log...

I have uploaded PROGRAM\BATTLE_INTERFACE\utils.c. Updated 27.05.2018. @Grey Roger, you may look it for the next update.
 

Attachments

  • utils.c
    12.3 KB · Views: 203
Last edited:
I'm not sure it's fully correct yet. As it turned out, I had a savegame with a damaged ship, so I put that file into place and direct-sailed around for a few days, watching the sail status and the stock of sailcloth at the turn of each day.

The amount repaired each day seemed to increase - not just the percentage per day shown on the "Ship" screen, but the actual amount repaired.
Day 1: sails 83%, 48 sailcloth
Day 2: sails 86%, 36 sailcloth (3% repaired for 12 sailcloth)
Day 3: sails 90%, 21 sailcloth (4% repaired for 15 sailcloth)
At this point I got lucky. You occasionally run into drifting cargo while direct-sailing, and what I ran into was a big bundle of sailcloth. :D
Day 3 end: 99 sailcloth
Day 4: sails 95%, 77 sailcloth (5% repaired for 22 sailcloth)
Day 5: sails 99%, 61 sailcloth (4% repaired for 16 sailcloth. The "Ship" screen now showed that I could repair 6553600.0%/day!)
Day 6: sails 100%, 61 sailcloth (presumably the 99% at start of day 5 was actually 99.9999...% and the carpenter spent day 5 trimming off the last threads to bring it up to 100% without needing any more cloth).

So it's not perfect but it's certainly an improvement in that you don't continue to lose sailcloth and gain XP. The carpenter had Repair skill 5 and, though he gained some XP, didn't get enough to go up to skill 6.
 
May be it is not correct completely, but where are the mistakes?
The amount repaired each day seemed to increase - not just the percentage per day shown on the "Ship" screen, but the actual amount repaired.
Yes, it will be, because it depends of % per day.
Discrepancy of amount of sailcloth per % per day for each day is, probably, because numbers was rounded.
6553600.0%/day! - :) For 99.(9)% it, probably, can be.:oops:

All what was done is:
Code:
float maxShipSP = GetCharacterShipSP(chref);
float fMakeRepair = (repPercent * maxShipSP)/100;
It corrects discrepancy of % with SP. Any other changes were not done.
 
Last edited:
I'm not sure how the whole sail repair calculation works, though your change certainly looks alright. And it's now included in the first update to the new installer. :onya
 
I had a similar problem in TEHO. I had to go into battleinterface/utils.c and do the following fix:

Code:
float GetAllSailsDamagePercent(ref chref)
{
...
    // LDH 20Feb17 fix constant repair message in ship interface
    if (SailPow > 100.0) SailPow = 100.0;
    chref.ship.sailstatus.sailpow = SailPow;
    chref.ship.sailstatus.saildmg = SailDmg;
     
    return SailPow;
}

It turned out that the SailPow being over 100.0 was causing the problem. It may be similar in PotC code.

Hook

Not working.. :no

P.S. Sorry. miss 2nd page.

upd/
checked code. looks like it over 100 people wrote those code and everyone wrote different functions to check sails status:(
Each code work different, one func show 100, another show 99, next one show 99,9999293949....o_O
 
Last edited:
Back
Top