• 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!

Serge Grey

Powder Monkey
1. Buld 14 Beta 4.1, Tuesday 27th March 2018 on Russian PoTC version with Russian Akella's patch 1.03r on it.
2.
I found that Repair function don't works properly. If the sails condition is nearly or 99%, it is no chance to repair it to 100%. When day passes, the repair skill increases, sailcloth decreases and 'percent per day' value increases too (even more than 100% per day), but sails condition is maximum of 99%! Skill raises even if i have no more sailcloth in the cargo hold!

By simple:

Day one: 98% of sails condition, skill 3(4 by Carpenter's toolkit) (53%), i have 10 units of sailcloth. Repairing --- skill 4 = 30.7% per day.
Day two: 99% of sails condition, skill 3(4) (57%), 7 units of sailcloth. Repairing = 60.14% per day.
Day three: 99% of sails condition, skill 3(4) (59%), 6 units of sailcloth. Repairing = 120.27% per day.

3. OK. Usually with this bug error.log is not appears, but now it is. I have used fast travel function in this save game.
4. I have only changed \Program\internalsettings.h:

// Included in Iron Man Mode:
OPEN_SEA_MOD
WORLDMAP_DISABLED
SAILTO_DISABLED
ONSEA_DATA_DISABLED
REALISTIC_ABILITIES
ITEM_REALISM

all to "1" value. And options in the game menu.

5. OK. You may wait for two days and try it yourself.
 

Attachments

  • compile.log
    17.5 KB · Views: 234
  • error.log
    126 bytes · Views: 239
  • system.log
    50.4 KB · Views: 243
  • -=Serge=- Open Sea August 22nd, 1750 1.7z
    620.1 KB · Views: 266
I've certainly noticed that sails sometimes stay at 99% but didn't notice that the system was still deducting sailcloth and attempting to repair them. If it is, where should I look for the code to repair sails?
 
I've certainly noticed that sails sometimes stay at 99% but didn't notice that the system was still deducting sailcloth and attempting to repair them. If it is, where should I look for the code to repair sails?
This is about repairing while sailing, right?
I'm not quite sure where the responsible code is, but I'd start searching in "DailyCrewUpdate.c" as that is the one that gets called every midnight.
 
That can't be it. The only references to "repair" or "sail" which I can find in "DailyCrewUpdate.c" are in this line, triggered if you have any cursed coins:
Code:
if(sti(pchar.curseddays)==25)   LogIt("Captain, the crew is really not happy with this whole curse business. They work SO HARD at repairing the sails, but it appears to have no effect!");

Also:
"error.log" only contains this, twice:
Code:
RUNTIME ERROR - file: seadogs.c; line: 738
Ghost A reference
Assuming @Serge Grey hasn't changed "seadogs.c", line 738 is the "return" line from this part of function "OnSave":
Code:
    if (bSeaActive) {
       seadogs_saveFrom = "sea";
       SaveAtSea();
       return;
I've no idea what a "Ghost A reference" is, but the error is probably being generated by saving the game, not by repairing sails.
 
That can't be it. The only references to "repair" or "sail" which I can find in "DailyCrewUpdate.c" are in this line, triggered if you have any cursed coins:
Bugger! In that case, I'm not entirely sure where it is... I'd have to search myself, but with no internet, that is really inconvenient.
Could you remind me in a week or so?

I've no idea what a "Ghost A reference" is, but the error is probably being generated by saving the game, not by repairing sails.
Correct. I don't know what it is either, but we've had that one occasionally ever since the stock game.
It doesn't seem to do any harm and I've always just ignored it. :shrug
 
In addition to that, there is a same problem with the 'Emergency Repairs' ability. The hull condition is not repairing up to 10% with this ability. There is only 9% maximum of it. Because of this there is perfect chance to gain unlimited number of experience! Now and as usual, it is no error.log appears with this bug.
 

Attachments

  • compile.log
    15.5 KB · Views: 217
  • system.log
    8.8 KB · Views: 222
  • -=Serge=- Open Sea September 4th, 1750.7z
    624.9 KB · Views: 175
Last edited:
'DailyCrewUpdate' is called from PROGRAM\calendar.c .
That file also contains a call to 'ProcessDayRepair', which is in PROGRAM\BATTLE_INTERFACE\BattleInterface.c .
That function seems to be the most likely culprit:
Code:
void ProcessDayRepair()
{
    //trace("Gauging: NEXTDAY_start PDR");
    int i, cn;
    float matQ, tmpf, repPercent;
    ref chref;
    for(i=0; i<COMPANION_MAX; i++)
    {
        cn = GetCompanionIndex(GetMainCharacter(),i);
        if(cn==-1) continue;
        chref = GetCharacter(cn);
        RepairAllCannons(&chref); // NK can qty. For now repair all fixable guns. Later go back and set repair rates. 05-04-19

        // расчет починки корпуса
        if( GetHullPercent(chref)<100.0 )
        {
            repPercent = GetHullRPD(chref);
            matQ = repPercent*GetHullPPP(chref);
            tmpf = GetRepairGoods(true,chref);
            if(tmpf<matQ)    { repPercent = tmpf/GetHullPPP(chref); }
            repPercent = ProcessHullRepair(chref,repPercent);
            matQ = repPercent*GetHullPPP(chref);
            RemoveRepairGoods(true,chref,matQ);
        }

        // расчет починки парусов
        if( GetSailPercent(chref)<100.0 )
        {
            repPercent = GetSailRPD(chref);
            matQ = repPercent*GetSailSPP(chref);
            tmpf = GetRepairGoods(false,chref);
            if(tmpf<matQ)    { repPercent = tmpf/GetSailSPP(chref); }
            repPercent = ProcessSailRepair(chref,repPercent);
            matQ = repPercent*GetSailSPP(chref);
            RemoveRepairGoods(false,chref,matQ);
        }
    }
    //trace("Gauging: NEXTDAY_end PDR");
}
 
"GetSailRPD and "GetSailSPP" are both in "PROGRAM\Characters\CharacterUtilite.c":
Code:
float GetSailRPD(ref _refCharacter) // ïðîöåíò ðåìîíòà ïàðóñîâ â äåíü
{
   int repairSkill = GetShipSkill(_refCharacter,SKILL_REPAIR);
   float damagePercent = 100.0 - GetSailPercent(_refCharacter);
   if(damagePercent==0.0) return 0.0;
   return repairSkill*10.0 / damagePercent;
}
Code:
int GetSailSPP(ref _refCharacter) // êîëè÷åñòâî ïàðóñèíû íà îäèí ïðîöåíò ïî÷èíêè
{
   return 9-GetCharacterShipClass(_refCharacter);
}
"GetSailRPD" is probably "Sail repaired per day" and is probably the 30.7%, 60.14% and 120.27% you were seeing. Reversing the calculation and basing on your effective skill of 4, those would be for damages of 1.30%, 0.67% and 0.33% respectively - or 98.7%, 99.33% and 99.67% sails remaining, which round off to 98%, 99% and 99%. I'm not sure what "GetSailRPD" is a percentage of, though - percentage of the damage percent which can be repaired?

"GetSailSPP" just returns the inverse of your ship's tier level. If you're still in the English Bark, which is tier 7, then "GetSailSPP" is 2.

"ProcessSailRepair" is in "PROGRAM\BATTLE_INTERFACE\utils.c" and is a lot more complex:
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 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;
}
I can't make much sense of what it's doing with the numbers generated by "GetSailRPD" and "GetSailSPP". And that's why, not wanting to risk breaking it even more, I haven't tried to do anything about this before the next installer is done.
 
And that's why, not wanting to risk breaking it even more, I haven't tried to do anything about this before the next installer is done.
OK, it is right. I see it is not very simple to find out where the error is. :)

I'm not sure what "GetSailRPD" is a percentage of, though - percentage of the damage percent which can be repaired?
As the description says (// процент ремонта парусов в день) it is percent of a sails repairing per day. But for repair skill of 4( if GetShipSkill(_refCharacter,SKILL_REPAIR)=4) and sails of 98% (if GetSailPercent(_refCharacter)=98), it will return 4*10/2=20 or about (damagePercent is float), when in the game it is 30.7 per a day.:unsure

I have started with GetSailPercent(_refCharacter). ProcessDayRepair() has chref = GetCharacter(cn) and cn = GetCompanionIndex(GetMainCharacter(),i). In attempt to understand what the CheckAttribute function does i have something strange as the result (see attached file) in console for this code:
Code:
int cn = GetCompanionIndex(GetMainCharacter(),1);
logit(cn);
Why?!

error.log has next for ever time i have pressed f12:
RUNTIME ERROR - file: battle_interface\loginterface.c; line: 189
CreateMessage: Invalid Data

I have found it without problems, but it will be good to say in the tutorial (new-horizons-Coding-101 | PiratesAhoy!) where console.c is. :)
 

Attachments

  • result.tga
    3.8 MB · Views: 255
Last edited:
As the description says (// процент ремонта парусов в день) it is percent of a sails repairing per day. But for repair skill of 4( if GetShipSkill(_refCharacter,SKILL_REPAIR)=4) and sails of 98% (if GetSailPercent(_refCharacter)=98), it will return 4*10/2=20 or about (damagePercent is float), when in the game it is 30.7 per a day.:unsure
For sails of exactly 98%, yes. But the 98% you see in the report is rounded off - the real sail percentage could be anything between 98.0% and 98.99999...% If "GetSailRPD" has returned 30.7 then the sail value is 98.7%, which rounds off to 98%.

I have started with GetSailPercent(_refCharacter). ProcessDayRepair() has chref = GetCharacter(cn) and cn = GetCompanionIndex(GetMainCharacter(),i). In attempt to understand what the CheckAttribute function does i have something strange as the result (see attached file) in console for this code:
Code:
int cn = GetCompanionIndex(GetMainCharacter(),1);
logit(cn);
Why?!

error.log has next for ever time i have pressed f12:
RUNTIME ERROR - file: battle_interface\loginterface.c; line: 189
CreateMessage: Invalid Data
"logit" is expecting a string. You're giving it an integer. Try:
Code:
int cn = GetCompanionIndex(GetMainCharacter(),1);
logit("" + cn);
Personally I like to put a bit of text there just to make sure that the number I see on the screen is from the "logit" line, e.g.
Code:
logit("Companion 1 has index " + cn);

As for CheckAttribute, it just checks if a given attribute exists. For example, 'if( CheckAttribute(arSail,"mastFall") )' checks if arSail, whatever that is, has the attribute "mastFall". If it doesn't then 'tmpstr = "ship.masts."+arSail.mastFall;' would cause an error.
 
If "GetSailRPD" has returned 30.7 then the sail value is 98.7%
Certainly.

"logit" is expecting a string. You're giving it an integer. Try:
Code:
int cn = GetCompanionIndex(GetMainCharacter(),1);
logit("" + cn);
Tutorial says:
It will show “42” on the screen. Now if you are paying attention you might have noticed we have given logit a int value as argument while it needs a string. This we can do because the engine will convert it to a string automaticly. Not all variables are converted with the same ease, but integers go fine.

Thanks, it works!

Personally I like to put a bit of text there just to make sure that the number I see on the screen is from the "logit" line, e.g.
Good idea, thanks.

As for CheckAttribute, it just checks if a given attribute exists. For example, 'if( CheckAttribute(arSail,"mastFall") )' checks if arSail, whatever that is, has the attribute "mastFall". If it doesn't then 'tmpstr = "ship.masts."+arSail.mastFall;' would cause an error.
Thank you, now it is clear.
 
Tutorial says:
It will show “42” on the screen. Now if you are paying attention you might have noticed we have given logit a int value as argument while it needs a string. This we can do because the engine will convert it to a string automaticly. Not all variables are converted with the same ease, but integers go fine.
You appear to have found otherwise. ;)

In any case, it's a good idea to get into the habit of using the correct types. There have definitely been problems in the past because someone gave the wrong data type to a function, which then did not work quite the way it was meant to.
 
In any case, it's a good idea to get into the habit of using the correct types. There have definitely been problems in the past because someone gave the wrong data type to a function, which then did not work quite the way it was meant to.
Very true! Got some massive confusion once when integers and floats got mixed up.
Even professional programmers didn't see that coming, so that took quite some doing to untangle. :shock
 
I have only:

Before system goes to ProcessSailRepair repPercent = 5.0289. Then it changes to 1.3303 into it and goes next into OneSailDmgRepair. I have noted that OneSailDmgRepair was called twice in the first day with fDmgRepair=1.3303 and fDmgRepair=0.79252 values.

There are two cases of if(fDmgRepair>=fSailDmg) in the first day:

1) If fDmgRepair=1.3303 >= fSailDmg=0.53782 (what is it?) requirement works, DeleteOneSailHole works and OneSailDmgRepair returns fSailDmg to decrease it from fMakeRepair(1.3303) in ProcessSailRepair. 1.3303-0.53782=0.79248, what approximately(why?) equal to fDmgRepair=0.79252 (the second entering value of OneSailDmgRepair function).

2) If fDmgRepair=0.79252 >= fSailDmg=2.1229 (what is it?) not works, fSailDmg -= fDmgRepair=2.1229-0.79252=1.33038 and i do not know how to understand what next "object vairables" as "arSail.hd" and "arSail.hc" means:
Code:
float sailDmgMax = GetCharacterShipSP(chref) * stf(arSail.sp); //200*0.12737=25.474 -?
    int iAfterHole = GetNeedHoleFromDmg( fSailDmg, sailDmgMax, sti(arSail.mhc) ); //iAfterHole = 1 (counts holes), sti(arSail.hc) = 0 in the next line
    if( sti(arSail.hc) > iAfterHole )
    {
        arSail.hd = DeleteOneSailHole( sti(chref.index), GetAttributeName(arSail), GetAttributeName(arSailNode), sti(arSail.hd), sti(arSail.hc)-iAfterHole );
        arSail.hc = iAfterHole;
    }
    arSail.dmg = fSailDmg; //1.33038
    return fDmgRepair; // 0.79252, it equals entering value, then

if(fMakeRepair<=0.0) {break;} //in the ProcessSailRepair function. It must be 100% of sails, doesn't it?
 
Last edited:
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
 
What is SailPow ? SailPoints or Sails Power? GetCharacterShipSP, probably, returns something same. But what it means, current sails condition? If it is, it must not be 200.

About damage - there is GetNeedHoleFromDmg function. And in variables, which are not clear for me, such as "sailDmgMax".
 
Last edited:
As far as I know, it's used as sail power. If it is 100, that means the sails are operating at 100%. If this number went over 100, it caused problems similar to what you've mentioned.

Hook
 
As far as I know, it's used as sail power. If it is 100, that means the sails are operating at 100%. If this number went over 100, it caused problems similar to what you've mentioned.
Thank you, Larry, but i don't know what variable is using for same purpose.

GetCharacterShipSP function, probably, is not using for that. It has a value of 200, but it is a part of GetSailPercent and last returns correct value (fpsp=98.67).
_refCharacter.Ship.SP=197.34 into GetSailPercent, what is it?

One interesting note: in the game you may see repairing value of 30.7 % per day, but GetSailRPD returns 30.067.
 
Back
Top