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

Medium Priority 3D Sailing Mode: Flag-related Error Log

I wished I had any clue on how that one can occasionally be generated.
A save at sea with that error active may allow it to be replicated.
That should help....
 
Got this one again today, with a 7 even!
Code:
RUNTIME ERROR - file: sea_ai\AIShip.c; line: 90
invalid index 7 [size:5]
RUNTIME ERROR - file: sea_ai\AIShip.c; line: 90
function 'CreateFlagEnvironment' stack error
This is where the error is triggered:
Code:
  for (i = 0; i < shipsqty; i++)
   {
     if (locidx < 0) {
       if (Ships[i] < 0) continue;
       chr = GetCharacter(Ships[i]);
     } else {
       if (iShips[i] < 0) continue;
       chr = GetCharacter(iShips[i]);
     }
     if (sti(chr.nation) != PIRATE) continue;
     GetPirateFlag(chr, &ntexture);
     if (!IsEntity(&PirateFlag[ntexture])) { // <----------------- HERE ------------------
       sid = "" + ntexture;

From globals.c and AIShip.c:
Code:
#define PIRATEFLAGS_TEXTURES_QUANTITY  5 // JRH: 6 are supported, but not yet used
[...]
object PirateFlag[PIRATEFLAGS_TEXTURES_QUANTITY], PiratePennant[PIRATEFLAGS_TEXTURES_QUANTITY];
So it IS correct that the "array size" is indeed 5 and not 7.
But what I don't understand is how GetPirateFlag can return '7' as ntexture in the first place???

Here's that full function from PROGRAM\BATTLE_INTERFACE\Flags.c:
Code:
int GetPirateFlag(ref chr, int ntex)
{
   ntex = 0;
   // Use character-specific flag if available
   if (CheckAttribute(chr, "Flags.Pirate.texture")) ntex = sti(chr.Flags.Pirate.texture);
   if (CheckAttribute(chr, "Flags.Pirate")) return sti(chr.Flags.Pirate);
   if (IsCompanion(chr))
   {
     ref PChar = GetMainCharacter();
     ntex = sti(PChar.Flags.Pirate.texture);
     return sti(PChar.Flags.Pirate);
   }
   else
   {
     ref cmdr = Group_GetGroupCommander(GetGroupIDFromCharacter(chr));
     if (!CheckAttribute(cmdr, "Flags.Pirate") || !CheckAttribute(cmdr, "Flags.Pirate.texture")) {
       ntex = rand(PIRATEFLAGS_TEXTURES_QUANTITY - 2); //PW: -2 to disable last row in random encounters
       cmdr.Flags.Pirate.texture = ntex;
       cmdr.Flags.Pirate = rand(FLAGS_PICTURES_QUANTITY_PER_TEXTURE - 2); // PB: -2 to disable last column in random encounters
       chr.Flags.Pirate.texture = ntex;
       chr.Flags.Pirate = sti(cmdr.Flags.Pirate);
       return sti(chr.Flags.Pirate);
     }
     ntex = sti(cmdr.Flags.Pirate.texture);
     return sti(cmdr.Flags.Pirate);
   }
}
It is this line that generates the number:
Code:
ntex = rand(PIRATEFLAGS_TEXTURES_QUANTITY - 2);
But that works out as "rand(3)" and therefore cannot possibly return a value of 5, let alone 7.

Why am I not seeing it?

This whole "Different Flags" functionality has never been willing to work 100% reliably for some reason.
I've already made several huge simplifications to it just to get it to behave itself.
But still we've got this, Unconfirmed Bug - Flag changing appearance without changing allegiance | PiratesAhoy! AND Engine Limitation - Graphical Anomalies | PiratesAhoy! .
All related to the same feature. :modding
 
There is also this in PROGRAM\SEA_AI\sea.c:
Code:
void LoadShipsToSea(int iNumShips, string sGName, int iNation, int iGeraldSails)
{
   ref rPlayer = GetMainCharacter();
   ref rCommander;
   int nflag1, ntex1, nflag2, ntex2;
   nflag2 = GetPirateFlag(rPlayer, &ntex2);
   for (int j = 0; j < iNumShips; j++)
   {
     int iFantomIndex = FANTOM_CHARACTERS + iNumFantoms - iNumShips + j;
     ref rFantom; makeref(rFantom, Characters[iFantomIndex]);

     rFantom.id = "fenc_" + iFantomIndex;
[...]
     if (iNation == PIRATE) {
       if (j == 0) {
         nflag1 = GetPirateFlag(rCommander, &ntex1);
         if (nflag1 == nflag2 && ntex1 == ntex2) {
           if (nflag1 == 0)
             rCommander.Flags.Pirate = nflag1 + 1;
           else
             rCommander.Flags.Pirate = nflag1 - 1;
         }
       } else {
         rFantom.Flags.Pirate = GetPirateFlag(rCommander, &nflag1);
         rFantom.Flags.Pirate.texture = nflag1;
       }
     }
I'm not quite sure now what that is supposed to be doing. :confused:
 
@Levis, @jsv and/or @pedrwyth: Can you have a look at the above if you spot the issue by any chance?
I'm not seeing it, so still am at quite a loss how this is even possible. :shock
 
@Pieter Boelen I think we should add a trace there if the number is larger then the index we dump chr to see why this is happening etc.
I can probably add that tomorrow, if we add an onscreen message to have them upload the compile log we can check :).
 
How's this?
Code:
     GetPirateFlag(chr, &ntexture);
     if (ntexture > PIRATEFLAGS_TEXTURES_QUANTITY)
     {
       TraceAndLog("CreateFlagEnvironment ERROR - Too high pirate flag number. Please post your compile.log file at piratesahoy.net!");
       DumpAttributes(chr);
     }
     if (!IsEntity(&PirateFlag[ntexture])) {
 
Add these lines too in the if:

Code:
ref cmdr = Group_GetGroupCommander(GetGroupIDFromCharacter(chr));
trace("============================COMMANDER=================");
DumpAttributes(cmdr);
 
There seem to be 3 possible sources of the flag, so I'd dumped main character as well.
 
There seem to be 3 possible sources of the flag, so I'd dumped main character as well.
if it where the mainplayer it should pop up very often. but better to be safe then sorry maybe...
 
Add these lines too in the if:

Code:
ref cmdr = Group_GetGroupCommander(GetGroupIDFromCharacter(chr));
trace("============================COMMANDER=================");
DumpAttributes(cmdr);
Like this?
Code:
    if (ntexture > PIRATEFLAGS_TEXTURES_QUANTITY)
     {
       TraceAndLog("CreateFlagEnvironment ERROR - Too high pirate flag number. Please post your compile.log file at piratesahoy.net!");
       DumpAttributes(chr);
       ref cmdr = Group_GetGroupCommander(GetGroupIDFromCharacter(chr));
       trace("============================COMMANDER=================");
       DumpAttributes(cmdr);
     }
Done. :cheers
 
Today I again got the famous error.log entry:
Code:
RUNTIME ERROR - file: sea_ai\AIShip.c; line: 100
invalid index 5 [size:5]
RUNTIME ERROR - file: sea_ai\AIShip.c; line: 100
function 'CreateFlagEnvironment' stack error

For reference, here is the relevant code:
Code:
#define PIRATEFLAGS_TEXTURES_QUANTITY  5 // JRH: 6 are supported, but not yet used

[...]

object Pennant, MerchantFlag, MerchantPennant, FortFlag;
object PirateFlag[PIRATEFLAGS_TEXTURES_QUANTITY], PiratePennant[PIRATEFLAGS_TEXTURES_QUANTITY];
object PersonalFlag[PERSONALFLAGS_TEXTURES_QUANTITY], PersonalPennant[PERSONALFLAGS_TEXTURES_QUANTITY];

[...]
     if (ntexture >= PIRATEFLAGS_TEXTURES_QUANTITY)
     {
       TraceAndLog("CreateFlagEnvironment ERROR - Too high pirate flag number. Please post your compile.log file at piratesahoy.net!");
       DumpAttributes(chr);
       ref cmdr = Group_GetGroupCommander(GetGroupIDFromCharacter(chr));
       trace("============================COMMANDER=================");
       DumpAttributes(cmdr);
     }
     if (!IsEntity(&PirateFlag[ntexture])) { // <--------------------- ERROR HERE ---------------------
So there is an "invalid index" on the marked line, which I normally take to mean as "an index that exceeds the size of the matrix".
PirateFlag should have size 5 and PIRATEFLAGS_TEXTURES_QUANTITY is 5 as well.
Which means that if 'ntexture' is 5 or greater (which error.log confirms WAS the case here), I should get that logged to compile.log .
But that "CreateFlagEnvironment ERROR" does NOT get logged at all.

The only explanation I can think of is that the value of 'ntexture' changes between the
'if (ntexture >= PIRATEFLAGS_TEXTURES_QUANTITY)' line and the 'if (!IsEntity(&PirateFlag[ntexture]))' one.
Which begs the question: HOW IS THAT EVEN REMOTELY POSSIBLE!?!?
 
uhm.... if an array has a size of 5 then 5 is in invalid index because 0 is the first.

but that does seem to be set right in the code.... very weird indeed. You know for sure you didn't get it in the compile log?
 
Last edited:
In my version of AIship (5th Jan) the line still reads
Code:
if (ntexture > PIRATEFLAGS_TEXTURES_QUANTITY)
so an index of 5 would be ignored by the trace but fail the attribute check.

As to the failing index I am probably only showing how much I really don't understand references but couldn't the use of ntexture as a variable for PERSONAL flags (which can have higher numbers) interfere with the use of ntexture as a variable for PIRATE flags - isn't it the same location being referred to ??
 
In my version of AIship (5th Jan) the line still reads
Code:
if (ntexture > PIRATEFLAGS_TEXTURES_QUANTITY)
so an index of 5 would be ignored by the trace but fail the attribute check.
Indeed I had that wrong in an earlier modpack version, but I corrected it with the 10 Jan update.

As to the failing index I am probably only showing how much I really don't understand references but couldn't the use of ntexture as a variable for PERSONAL flags (which can have higher numbers) interfere with the use of ntexture as a variable for PIRATE flags - isn't it the same location being referred to ??
Maybe @Levis would know? This whole 'reference' business is also quite alien to me; I am finally beginning to sort-of understand it now.
But not quite.... :wp
 
Still looking into this one and it is STILL completely crazy. Look at this one:
Code:
     TraceAndLog("Getting pirate flag for " + GetMyShipNameShow(chr));
     flg = &PirateFlag[ntexture]);
     if (!IsEntity(flg)) {
       Trace("Loading PirateFlag[" + ntexture + "] for " + GetMySimpleName(chr));
       [...]
     }
     else
     {
       Trace("ALREADY LOADED PirateFlag[" + ntexture + "] for " + GetMySimpleName(chr));
     }
This is what gets written to compile.log:
Code:
Getting pirate flag for 'Cassandra'
Loading PirateFlag[1] for Velasconi Pinzon
Getting pirate flag for 'Concorde'
Note how I've got a "trace" statement in both the IF and the ELSE.
But while TraceAndLog gets called for TWO ships, I only get ONE trace.
So that means that somehow if if (!IsEntity(flg)) returns FALSE, it does NOT go to the "else" statement.

On what planet does THAT make any sense!?!? :shock

EDIT: Apparently if that part fails, then the entire function is aborted.
Or at least the for-loop that it is in. Messy....
 
Last edited:
Back
Top