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

Unconfirmed Bug Bad performance in battle

KillPhil

Corsair
Storm Modder
Just sailed to Barbados via Worldmap. When I entered 3D, some french ships spawned next to me, and my game began to stutter, like every 5 seconds - felt for me like it checked something every 5 seconds - so I opened error.log and found this:

RUNTIME ERROR - file: sea_ai\AIShip.c; line: 4519
NAN ERROR
RUNTIME ERROR - file: sea_ai\AIShip.c; line: 4519
NAN ERROR

I don't know if this is related, or perhaps reported before, but just in case ;)
 
Latest ZIP from WIP 4.1 from 23rd Sept.

The bad performance lastet even after I got to Bridgetown port (on land performance was fine). When I set sail again, it began to stutter again. I even saved and restarted the game, it didnt help. 3D sailing performance only was fine again after leaving the Barbados waters.
 
Can you upload your PROGRAM\sea_ai\AIShip.c file? I don't remember ever seeing "NAN ERROR" in PotC so I wonder where that is actually happening.

Is that error.log entry repeated a lot of times? Or did it get logged only once or twice?
 
Thanks, @Pillat

It is that last line here then:
Code:
// Calc min crew ratio
float fCrewMin = makefloat(GetMinCrewQuantity(&rCharacter)); // PRS3 - stf(rShip.MinCrew);
float fCrewCur = makefloat(GetCrewQuantity(&rCharacter));//stf(rCharacter.Ship.Crew.Quantity);//MAXIMUS
float fCrewMin25Percent = fCrewMin* 0.25; // NK no need to check attr _twice_...
arCharShip.Crew.MinRatio = Bring2Range(0.0, 1.0, fCrewMin25Percent, fCrewMin, fCrewCur);

Are you able to replicate this consistently? If so, replace the above code with:
Code:
// Calc min crew ratio
float fCrewMin = makefloat(GetMinCrewQuantity(&rCharacter)); // PRS3 - stf(rShip.MinCrew);
float fCrewCur = makefloat(GetCrewQuantity(&rCharacter));//stf(rCharacter.Ship.Crew.Quantity);//MAXIMUS
float fCrewMin25Percent = fCrewMin* 0.25; // NK no need to check attr _twice_...
Trace("fCrewMin = " + fCrewMin + ", fCrewCur = " + fCrewCur + ", fCrewMin25Percent = " + fCrewMin25Percent);
arCharShip.Crew.MinRatio = Bring2Range(0.0, 1.0, fCrewMin25Percent, fCrewMin, fCrewCur);
Then try it again. This will not fix anything, but should log the values being used in that calculation to compile.log so that hopefully that'll give some sort of clue on which of the three numbers is going wrong.

The error log was there like 500 times.
That confirms that the error logging must indeed be the direct cause of the lag.
 
I just had this yesterday in the last few minutes of playing, I don't know if I can reproduce it. But maybe - since this apparently has something to do with Crew - I should note that I reduced the min.crew for all ships in the ships_init.c and reduced the mincrew.forallguns in the Internalsettings.h
 
I should note that I reduced the min.crew for all ships in the ships_init.c and reduced the mincrew.forallguns in the Internalsettings.h
Maybe if one of those variables gets lower than it used to be, it could try to do a calculation with an irregular range of numbers.
Fo example if 'fCrewMin' is zero, I can imagine that code getting very confused.

So that could potentially explain it then. But I don't know that for sure.
If you do manage to replicate it, hopefully my suggestion will give a proper hint on what is going on.
 
a NAN error could only occur (I think) if the game does a square root of a negative number ... so please see if you can replicate it, and if changing the internal settings values helps.
 
Could someone show me the function definition of 'Bring2Range'? While I can make an educated guess of what that does, I don't really know for certain.
But I figure that must be where it somehow goes wrong.
 
Definitions can be found in both "seadogs.c" and "utils.c", but they're both commented out. "seadogs.c" also contains a declaration 'native float Bring2Range(float fMin1, float fMax1, float fMin2, float fMax2, float fValue);'.

Here's the commented out definition:
Code:
/*float Bring2Range(float fMin1, float fMax1, float fMin2, float fMax2, float fValue)
{
   if(fValue < fMin2) { fValue = fMin2; }
   if(fValue > fMax2) { fValue = fMax2; }
   float fDelta = (fValue - fMin2) / (fMax2 - fMin2);
   return fMin1 + fDelta * (fMax1 - fMin1);
}
*/
I've no idea what a 'native' declaration is - something hidden in the game engine, perhaps? If it does the same thing as the commented out version then no square roots are involved, but if fMax2 and fMin2 are the same then it will produce a division by zero. And if someone got their fMin's and fMax's the wrong way round then fValue will become equal to fMax2, fDelta will be 1, and the returned value will be fMax1 - fMin1 which will be negative.
 
I've no idea what a 'native' declaration is - something hidden in the game engine, perhaps?
I can pretty much guarantee that your interpretation there is correct. ;)

If the function isn't defined anywhere, then it must indeed be a game engine thing.

I assume then that it is functionally equivalent to what the commented out code states, but the actual implementation may differ.

If it does the same thing as the commented out version then no square roots are involved, but if fMax2 and fMin2 are the same then it will produce a division by zero.
The strange thing is that normally a "divide by zero" gets caught by the game code and actually shows in error.log as such.
Maybe because this is the game engine, we don't get the "nice" error log indicating "divide by zero", but a strange engine-sourced one about NAN (=Not A Number) instead.
But that is another assumption on my part. Only way to know for sure is to know what values went into that function using the Trace I suggested above.

I do seem to be doing a lot of assuming today. Unfortunately that means "to make an 'ass' out of 'u' and 'me'." Sorry about that.... :facepalm
 
Here are the definitions of the related functions:

template<class T> Bring2Range(T Min1, T Max1, T Min2, T Max2, T Value) { if (Value < Min2) Value = Min2; if (Value > Max2) Value = Max2; float Delta = float(Value - Min2) / float(Max2 - Min2); return Min1 + Delta * (Max1 - Min1); };

This is what the exposed 'native' calls, which in turn calls the above template:

_Bring2Range(VS_STACK * pS)
{
VDATA * pValue = (VDATA*)pS->Pop();
VDATA * pMax2 = (VDATA*)pS->Pop();
VDATA * pMin2 = (VDATA*)pS->Pop();
VDATA * pMax1 = (VDATA*)pS->Pop();
VDATA * pMin1 = (VDATA*)pS->Pop();

VDATA * pVR = (VDATA*)pS->Push(); if (!pVR) return IFUNCRESULT_FAILED;
pVR->Set(Bring2Range(pMin1->GetFloat(), pMax1->GetFloat(), pMin2->GetFloat(), pMax2->GetFloat(), pValue->GetFloat()));

return IFUNCRESULT_OK;
}

The 'Pop' takes each of the .c program parameters off of a stack and places the values in a VDATA object, that then tries to convert the parm value to a float that is passed into Bring2Range.

It is the Set function that is likely returning the NaN error, which would be the result of template Bring2Range not returning a valid float:

void DATA::Set(float value)
{
//if(bRef)
if(Data_type == VAR_REFERENCE)
{
if(pReference)
{
pReference->Set(value);
return;
}
Error(UNINIT_REF);
return;
}
if(bArray) {Error(NO_INDEX); return;}
Data_type = VAR_FLOAT;
fValue = value;
if(_isnan(fValue)) Error("NAN ERROR");
}
 
Wow, that's a real in depth answer!
Thanks, @ChezJfrey. :cheers

No problem.

It might be that the result of Bring2Range exceeds the float type range. Checking the parameters sent to the function, against what the function would calculate now that you can see what it does (this would have to be manually done with your trace log addition showing the values passed into it), that result in NaN error, can be compared to the acceptable range of float type: Type float

float
1.175494351 E – 38
3.402823466 E + 38
 
Back
Top