• 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 Boarding: Inconsistent Crashes Related to Looting

But where is that ProcessSailRepair itself?
BattleInterface.c

Maybe they had a low morale and surrendered? But then you should have gotten the dialog. Bit strange....
Not sure, I didn’t finish the boarding so I have no idea if the rest of the fleet had surrendered. However, since there was only two pirates, possibly Sloops, against 6 heavy warships, including my own flying British colours as well, their morale should have been very good. Hoisting would probably have some kind of effect, but since they had twice the power that I had it doesn’t really make sense. I literally just pulled up alongside and hoisted, giving me the boarding option.
 
BattleInterface.c
I have no access to my game files right now, otherwise I could have looked that up myself.
Can you post what that function looks like?

Not sure, I didn’t finish the boarding so I have no idea if the rest of the fleet had surrendered. However, since there was only two pirates, possibly Sloops, against 6 heavy warships, including my own flying British colours as well, their morale should have been very good. Hoisting would probably have some kind of effect, but since they had twice the power that I had it doesn’t really make sense. I literally just pulled up alongside and hoisted, giving me the boarding option.
In that case, I do not know.
 
Both functions, from the unedited file...
void ProcessDayRepair()
{
//trace("Gauging: NEXTDAY_start PDR");
int i, cn;
float matQ, tmpf, repPercent;
ref chref;
for(i=0; i<4; 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");
}
bool CheckInstantRepairCondition(ref chref)
{
//int tmpLangFileID = LanguageOpenFile("interface_strings.txt");
//boal -->
//if(!GetCharacterPerkUsing(chref,"InstantRepair")) return false;

//ccc realistic shipyard repair at anchorage only->
// LDH 02Oct06
if(!bMapEnter) return false;
//ccc repair <-

/*bool retRepair = GetCharacterPerkUsing(chref,"InstantRepair");
if(!retRepair)
{
int cn;
for(int i=1; i<4; i++)
{
cn = GetOfficersIndex(chref,i);
if(cn!=-1)
{
if(GetCharacterPerkUsing(GetCharacter(cn),"InstantRepair"))
{
retRepair = true;
break;
}
}
}
}*/ // ASVS commented that out, see below.
if(!GetOfficersPerkUsing(chref,"InstantRepair")) //ASVS - come on, we have a function for that, why not using it?
return false;
//boal <--

if(GetHullPercent(chref) < 90.0 && GetCargoGoods(chref, GOOD_PLANKS) > 0) return true;
return GetSailPercent(chref) < 90.0 && GetCargoGoods(chref, GOOD_SAILCLOTH) > 0;
}
 
I think this is the problem...
Code:
if(GetHullPercent(chref) < 90.0 && GetCargoGoods(chref, GOOD_PLANKS) > 0) return true;
return GetSailPercent(chref) < 90.0 && GetCargoGoods(chref, GOOD_SAILCLOTH) > 0;
I have no idea what effect it has on repairing the sails, but by changing it to the same as the hull I am getting through the decks.
Code:
if(GetHullPercent(chref) < 90 && GetCargoGoods(chref, GOOD_PLANKS) > 0) return true;
if(GetSailPercent(chref) < 90 && GetCargoGoods(chref, GOOD_SAILCLOTH) > 0) return true;
Yes, that’s set to true, and with sail cloths - it’s not crashing. I’ll have to keep tabs, maybe I’m just getting lucky.
 
Can you post ProcessSailRepair as well? That is the main one I am interested in.
 
Wait, hold on... I thought that was it, now I see that the function is simply calling it...
repPercent = ProcessSailRepair(chref,repPercent);
Okay, I don’t know where it is but I’ll have a good look.
 
You mean this?
Program\BattleInterface\utils.c said:
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;
}
 
Thanks! :cheers

I think for starters, you should remove the \\ in front of the lines in ProcessDayRepair() .
Then see if you can trigger the crash again to see if it got as far as "Gauging: NEXTDAY_end PDR" before the crash happened.

Assuming that indeed it didn't, then apparently the reason for the crashing is somewhere inbetween.
Then it is a matter of ruling things out.

For example, replace this:
Code:
void ProcessDayRepair()
{
//trace("Gauging: NEXTDAY_start PDR");
int i, cn;
With this:
Code:
void ProcessDayRepair()
{
trace("Gauging: NEXTDAY_start PDR");
return;
int i, cn;

OR this:
Code:
float ProcessSailRepair(ref chref, float repPercent)
{
if (repPercent == 0.0) return 0.0; // LDH out of sailcloth - 25Feb09
With this:
Code:
float ProcessSailRepair(ref chref, float repPercent)
{
return 0.0;

By a process of elimitation, hopefully you could narrow down the troublesome spot.

You can also add extra Trace lines inbetween so you can see how far it gets. That is how I often do my debugging as well.
 
I don’t know how the tracing works. But anyway...

I just got through 5 decks with the original files in place, looting pretty much everything. Why did it not crash? Probably because the enemy ship had sail cloths. If this is true then I’m wondering if there is a division-by-zero taking place. The following line refers to the number of sail cloths, so it’s feasible that the current sail strength is being divided by the amount of cloth, or something like that, so if that number is zero then there is a problem. I mean, so far as this line is concerned, it might as well read as return false as it would have the same effect. If it is indeed a division-by-zero then it needs to be caught before the calculation takes place, and thus the relevant function aborting, otherwise the process will exit. Maybe it is normally caught but for whatever reason this does not happen if it is a boarded ship.
Code:
 if (repPercent == 0) return 0 ;
Consider this... you cannot divide any number by zero, but you CAN divide zero by anything other than zero itself. This is where I think the sail cloths are relevant, it could be that the system is checking the player’s ship, returning zero because the player is not on his ship, and if it finds no cloth either then it returns another zero. If it does find cloth then it divides zero by that number and, therefore, returns as false rather than the game dying very painfully.

What this doesn’t necessarily explain, though, is why a crash doesn’t occur when the player’s own ship has no sails. So, I’ll assume that it simply cannot grab the required data if the player is on an enemy ship.

Why the system is checking the sails in the first place is another matter entirely, my suspicion here is that one variable, be it true or false, is being divided by another which is false (which, if I’m right, would blatantly be the number of sail cloths, or rather lack thereof).

Another thing to think about is whether or not this is happening in respect of the hull. If not then it would surely give good pointers as to the source.
 
Last edited:
I don’t know how the tracing works.
Simple; you add a line Trace("Whatever you want"); and when the game code passes that line, "Whatever you want" gets written to compile.log .

If this is true then I’m wondering if there is a division-by-zero taking place.
If I recall, normally that would show in error.log as "divide by zero" error.
 
Well... I guess that depends on whether or not the game catches the error. End of the day, if it’s a buffer under/overrun then the game could be exiting before it has had a chance to log the problem. Maybe that is precisely why there never seems to be anything in the logs about this error? I guess the system will say one of two things: “Nope, that’s an error and I can’t continue because...”, or it will be like, “MAYDAY!!”.
 
Well... I guess that depends on whether or not the game catches the error. End of the day, if it’s a buffer under/overrun then the game could be exiting before it has had a chance to log the problem. Maybe that is precisely why there never seems to be anything in the logs about this error? I guess the system will say one of two things: “Nope, that’s an error and I can’t continue because...”, or it will be like, “MAYDAY!!”.
Could indeed be. Use Trace to find out how far the code gets before crashing; that should tell us more. :doff
 
Im experiencing the same (and it seems a lot more this evening).
Don't know why it happens so much more (like once every boarding, basically can't loot anything).
 

Attachments

  • compile.log
    19.1 KB · Views: 140
  • error.log
    297 bytes · Views: 149
Okay. It’s definitely the sails, I’m boarding a pirate with no cloths and it is systematically bailing every time I loot, but it is not doing so with ships which do have cloths. I just don’t know if it’s relevant as to whether or not my own ship has any.

I’m doing something wrong with the trace because I’m seeing this...
COMPILE ERROR - file: battle_interface\utils.c; line: 208
Invalid Expression

Also, look at the screen shot. In this case, I managed to loot everybody on the top deck but as soon as I moved to the next one it crashed.
 

Attachments

  • Untitled.jpg
    Untitled.jpg
    207.6 KB · Views: 210
Last edited:
Hmm... actually, it doesn’t seem to matter if they have cloths. It’s just that it was working one moment when I’d make changes, and then it would crash if I reverted them. Now it’s acting differently.

Anyway, the only function I’m able to trace is ProcessSailDamage.
BattleInterface.c said:
float sailDmg = 0.0;
float sailDmgMax = GetCharacterShipSP(chref) * sailPower;
if( !CheckAttribute(arSail,"dmg") ) { sailDmg = 0.0; }

trace("getShip: "+GetCharacterShipSP(chref))
trace("sailDmg: "+sailDmg)
trace("sailDmgMax: "+sailDmgMax)
trace("sailPower: "+sailPower)
compile.log said:
getShip: 200
sailDmg: 0.
sailDmgMax: 33.832
sailPower: 0.16916
getShip: 200
sailDmg: 0.
sailDmgMax: 20.86
sailPower: 0.1043
getShip: 200
sailDmg: 0.
sailDmgMax: 14.591
sailPower: 7.2954e-002
getShip: 200
sailDmg: 0.
sailDmgMax: 91.625
sailPower: 0.45813
getShip: 200
sailDmg: 0.
sailDmgMax: 39.092
sailPower: 0.19546
That, there, is a very odd number. So now I wonder if this is causing an overflow because the number is too large for memory, or it is being converted to zero and thus causing a division-by-zero somewhere along the lines.
 
Last edited:
Okay. Hard to confirm for sure, but I think the above trace only shows when I have no sail cloths. I did this just now and the enemy ship had none either, and while it did not crash while looting the sea in the background went all funky like in the above attachment. I think sailPower could be the key here.

Also... while this could be related, it didn’t cause a crash so it may not be...
trying to spawn item: medical1 with rarity=6.0364e-002 itemProb=0.96
trying to spawn item: roseskull with rarity=0.41241 itemProb=6.e-002
trying to spawn item: skillbook2 with rarity=0.36389 itemProb=2.4e-002
trying to spawn item: jewelry16 with rarity=0.11673 itemProb=2.4e-002
trying to spawn item: jewelry1 with rarity=0.88385 itemProb=6.e-002
trying to spawn item: pistolmket with rarity=7.7637e-002 itemProb=6.e-002
trying to spawn item: chinatiger with rarity=0.74936 itemProb=3.6e-002
There were lots of them, these are but a few. It’d be no wonder if numbers like these are causing problems.
 
Last edited:
Sorry to keep on posting, I’m done with this for today anyhow. :)

I have removed sail cloths from being spawned in ship inventories in SEA_AI\AIFantom.c; having none seems to trigger the bug more easily.

I have also removed these lines...

BattleInterface.c: #event_handler("NextDay","ProcessDayRepair");
Utils.c: #event_handler("evntActionRepair","procActionRepair");

While this effectively breaks the active sail repairs, I can only assume, it seems to be doing something to stop the crashes.

There is something about the sea in the background going weird when a body is looted, it would be unsurprising if this is related. Have a look at the image I posted, it’s very odd. If the game is usually crashing at this point then people probably don’t notice the peculiar sails floating in the backdrop.
:bounce “Sail ahoy, cap’n!
:keith “How many decks?”
:nerbz “Err... none, cap’n!”
 
Last edited:
Also, look at the screen shot.
I think the game engine does that so that when you return to 3D Sailing Mode, all ships are still in place.
It probably always happen, but usually you don't notice. Good example, that!

While this effectively breaks the sail repairs, I can only assume, it seems to be doing something to stop the crashes.
Instead of removing those lines, I'd propose this instead:
Code:
void ProcessDayRepair()
{
   //trace("Gauging: NEXTDAY_start PDR");
   if( bSeaActive && bAbordageStarted ) return; // <------------- Abort this function during boarding -----------------
   int i, cn;

And/or an extra line here:
Code:
void procActionRepair()
{
   int chrIdx = GetEventData();
   int eRepType = GetEventData();
   if(chrIdx<0) return;
   if(!bSeaActive)   return;
   if( bAbordageStarted) return; // <------------- And this one too -----------------
   ref chref = GetCharacter(chrIdx);

That isn't an ideal solution, because I think that aborts a bit too much.
But if it works, then at least we know in which direction to look.

Then it is a matter of moving these "abort" lines later and later into the process until the problem returns.

Or don't put the lines in there, but just scatter Trace lines all over those functions instead.
Often I just use Trace("Part 1"); and Trace("Part 2"); and then check compile.log after the crash to see which "parts" it did and did not log.
 
Back
Top