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

Another question about flags

Jack Rackham

ex train dispatcher
Quest Writer
Storm Modder
I need to raise a certain pirate flag on land. Now if I set everything to PIRATE I always get the Rackham style flag. It doesn't help if I for ex try : cmdr.Flags.Pirate = 4; cmdr.Flags.Pirate.texture = 2;
like it does for PERSONAL_NATION.

So my idea id to add that specific pirate flag to the personal flags menu (many unused ones) and do it that way.

Any one having any objections to that?
 
If you search for 'PirateOverride' in PROGRAM\BATTLE_INTERFACE\Flags.c, you'll see exactly why you have this problem.
While I was the one who wrote that code, I don't like it any more than you do; I was basically forced to do it.
I remember beating my brain against the PotC code repeatedly trying to fix this the correct way, but never managed it. :modding
 
Yes, I have seen the PirateOveride thing but don't know what problems it 'll cause by removing it.
What happened without it?
 
What happened
The correct flags still wouldn't show up and, with some luck, the game would crash.
I remember doing some very hard work on it for your "plenty of pirate ships around the lighthouse" scene in Woodes Rogers.
This was the best I managed, but I'm not at all happy with it. :facepalm
 
In flags.c under SetFortFlag and SetTownFlag PIRATE nation is outcommented. Part of the same fix?
 
Ok I made a test: skipped PirateOverrite and skipped the 2 outcommented situations as per above:
red pirate flag.jpg


Maybe I was lucky. Maybe I'll make an exception for WoodesRogers quest to not risk too much possible trouble everywhere.
 
In flags.c under SetFortFlag and SetTownFlag PIRATE nation is outcommented. Part of the same fix?
I think so. I can't quite remember, because it was quite some time ago.
The one thing I do remember is that I could never get it to work the way it should.
But I don't know why not and it doesn't make sense. If it works for Personal, why shouldn't it work for Pirate?
It's all mod-added functionality after all, so we should have full control over it!
 
Ok I made a test: skipped PirateOverrite and skipped the 2 outcommented situations as per above:
See what happens if you start a FreePlay game so that no "Woodes Rogers" stuff is in play. Sail to Turks Island and see if its fort shows a proper flag. Ships should not be affected; if I read the code correctly, PirateOverride is only set if the flag is not a ship's flag or pennant. But it wouldn't do any harm to find some pirate ships and check that their flags show up properly as well.
I think so. I can't quite remember, because it was quite some time ago.
The one thing I do remember is that I could never get it to work the way it should.
But I don't know why not and it doesn't make sense. If it works for Personal, why shouldn't it work for Pirate?
It's all mod-added functionality after all, so we should have full control over it!
The code is not the same. Here's 'GetPirateFlag':
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
       }
       ntex = sti(cmdr.Flags.Pirate.texture);
       chr.Flags.Pirate.texture = ntex;
       chr.Flags.Pirate = sti(cmdr.Flags.Pirate);
       return sti(cmdr.Flags.Pirate);
   }
}
And here's 'GetPersonalFlag':
Code:
int GetPersonalFlag(ref chr, int ntex)
{
   // PB -->
   // Use character-specific flag if available
   if (CheckAttribute(chr, "Flags.Personal.texture")) ntex = sti(chr.Flags.Personal.texture);
   if (CheckAttribute(chr, "Flags.Personal")) return sti(chr.Flags.Personal);

   // Otherwise use the player's own flag
   ref PChar = GetMainCharacter();
   ntex = sti(PChar.Flags.Personal.texture);
   return sti(PChar.Flags.Personal);
   // PB <--
/*   ntex = 0;
   if(IsCompanion(chr))
   {
       ref PChar = GetMainCharacter();
       ntex = sti(PChar.Flags.Personal.texture);
       return sti(PChar.Flags.Personal);
   }
   else
   {
       if (CheckAttribute(chr, "Flags.Personal.texture")) ntex = sti(chr.Flags.Personal.texture);
       if (CheckAttribute(chr, "Flags.Personal")) return sti(chr.Flags.Personal);
       ref cmdr = Group_GetGroupCommander(GetGroupIDFromCharacter(chr));
       if (!CheckAttribute(cmdr, "Flags.Personal"))
       {
           ntex = rand(PERSONALFLAGS_TEXTURES_QUANTITY - 1);
           cmdr.Flags.Personal.texture = ntex;
           cmdr.Flags.Personal = rand(FLAGS_PICTURES_QUANTITY_PER_TEXTURE - 1);
           chr.Flags.Personal.texture = ntex;
           chr.Flags.Personal = sti(cmdr.Flags.Personal);
           return sti(chr.Flags.Personal);
       }
       ntex = sti(cmdr.Flags.Personal.texture);
       return sti(cmdr.Flags.Personal);
   }*/
}
'GetPersonalFlag' has the same code as 'GetPirateFlag', all commented out and replaced by a shorter, simpler version - your work, apparently. :onya The main differences seem to be that 'GetPirateFlag' (and the original 'GetPersonalFlag') contains a call on 'Group_GetGroupCommander' - perhaps that doesn't work for anything other than ships? And 'GetPirateFlag', if it can't find a defined flag, picks one at random, whereas 'GetPersonalFlag' defaults to the player's flag. That's fine for forts because the only ways a fort will have a Personal flag are if you captured it for yourself, or if some quest sets it and presumably sets the attributes for the texture as well.
 
'GetPersonalFlag' has the same code as 'GetPirateFlag', all commented out and replaced by a shorter, simpler version - your work, apparently. :onya
Yep, because I couldn't get it to work properly.
I'd welcome if somebody else were to give it a try.
Maybe I overlooked something. I'd hope so!

The main differences seem to be that 'GetPirateFlag' (and the original 'GetPersonalFlag') contains a call on 'Group_GetGroupCommander' - perhaps that doesn't work for anything other than ships?
I can't quite remember now, but I do believe there is some sort of code in place to make fort commanders their own group commander too.
Not sure if that works properly, though...

Ships should not be affected; if I read the code correctly, PirateOverride is only set if the flag is not a ship's flag or pennant.
That is very much correct.
The last time I worked on this code was specifically for @Jack Rackham's scene where he wanted different pirate ships to show their correct individual flags.
That was the main purpose, so when I couldn't get the fort to behave itself and it kept taking up too much of my time and effort, I gave up and thoroughly simplified the code for pirate forts.
After all, in its current simplified form, at least it isn't wrong. And it doesn't crash the game anymore either.
But it does misses out on some functionality that does work for Personal.

I think some of the confusion also comes because Pirate has a general nation flag in the fort flag files. This is the one that's used.
To get the customized pirate flags to work for forts, a different flag texture file must be loaded instead.
This means an exception to the regular fort flag code, which makes it extra complex.
 
See what happens if you start a FreePlay game so that no "Woodes Rogers" stuff is in play. Sail to Turks Island and see if its fort shows a proper flag.
To get the customized pirate flags to work for forts, a different flag texture file must be loaded instead.
I tested on Redmond:

Code:
CaptureTownForNation("Redmond", PIRATE);
ref cmdr = CharacterFromID("Redmond Commander");
cmdr.nation = PIRATE;
cmdr.Flags.Pirate = 4; cmdr.Flags.Pirate.texture = 2;   
SetCharacterShipLocation(pchar, "Redmond_port");
SetNextWeather("Clear");
Pchar.quest.JRH_rain = "Clear";
red fort flag.jpg


Without cmdr.Flags.Pirate = 4; cmdr.Flags.Pirate.texture = 2; no flag at all.
 
Yep, because I couldn't get it to work properly.
I'd welcome if somebody else were to give it a try.
Maybe I overlooked something. I'd hope so!
My point is, 'GetPersonalFlag' is the simplified one, and it works. 'GetPirateFlag' is the original one, and - at least on forts - apparently it doesn't work. So the switch in 'SetFortFlag' based on nation has the section for PIRATE commented out. (And the section for PRIVATEER_NATION as well, though that's never going to be needed unless someone figures out a reason to set a fort to PRIVATEER_NATION for quest purposes.)

Perhaps defining a new function 'GetPirateFortFlag', using the same simplified code as 'GetPersonalFlag', would work? This would mean a pirate fort would default to using the player's pirate flag if the commander doesn't have one defined, which in turn means Turks Island fort commander will need a pirate flag defined. And probably the Tortuga fort commander as well, for when Tortuga is owned by pirates, e.g. in "Hoist The Colours".
 
I tested on Redmond:

Code:
CaptureTownForNation("Redmond", PIRATE);
ref cmdr = CharacterFromID("Redmond Commander");
cmdr.nation = PIRATE;
cmdr.Flags.Pirate = 4; cmdr.Flags.Pirate.texture = 2;  
SetCharacterShipLocation(pchar, "Redmond_port");
SetNextWeather("Clear");
Pchar.quest.JRH_rain = "Clear";

Without cmdr.Flags.Pirate = 4; cmdr.Flags.Pirate.texture = 2; no flag at all.
I expected it to show your own pirate flag. But it does confirm part of what I thought - pirate fort commanders will need those "Flags.Pirate" and "Flags.Pirate.texture" lines added to their definitions.

Did you try sailing to Turks Island? That should already be Pirate, and as the commander's definition in "PROGRAM\Characters\init\FortCommandants.c" has no flag lines, it will probably do the same as Redmond. If so, see what happens if you add the lines to "FortCommandants.c" and start a new game.
 
I tried Turks but found no flags in town and no forts either. Where are those?
Tomorrow I'll try something in the style @GreyRoger suggests.
 
With the code as I left it, I'd expect the default pirate flag to work on forts and nothing else.
I'm surprised setting a custom pirate flag for the commander has any impact at all (by making the flag disappear altogether).

My theory: the game still loaded the "default" fort flag texture, but you're using a different one.
The two files don't match up, so nothing shows instead.

Clearly this code is still bugged
Not as badly as it once was, but still wrong.
 
Is it not the other way round?
I tested on Redmond:

Code:
CaptureTownForNation("Redmond", PIRATE);
ref cmdr = CharacterFromID("Redmond Commander");
cmdr.nation = PIRATE;
cmdr.Flags.Pirate = 4; cmdr.Flags.Pirate.texture = 2;  
SetCharacterShipLocation(pchar, "Redmond_port");
SetNextWeather("Clear");
Pchar.quest.JRH_rain = "Clear";
The screenshot then shows the flag corresponding to those custom flag attributes.

Without cmdr.Flags.Pirate = 4; cmdr.Flags.Pirate.texture = 2; no flag at all.
No custom flag attributes, and no default flag displayed.

This means fort commanders must have "Flags.Pirate" attributes assigned if they are to display Pirate flags. It may be necessary to assign the attributes to all fort commanders, in case some pirate player decides to capture a town and hand it to Pirates instead of keeping it for himself; the fort would then need to be able to display a Pirate flag.
 
I tried Turks but found no flags in town and no forts either. Where are those?
Tomorrow I'll try something in the style @GreyRoger suggests.
There should certainly be a fort at Turks Island. Sail to the port, hoist a non-pirate flag, and look for the cannons shooting at you. :pirate41:

Fort commanders are all defined in "PROGRAM\Characters\init\FortCommandants.c". For example, Turks Island:
Code:
   ch.old.name = "Marius";
   ch.old.lastname = "Yberville";
   ch.name    = TranslateString("","Marius");
   ch.lastname    = TranslateString("","Yberville");
   ch.id       = "Grand Turk Commander";
   ch.model = "50Grey1";
   ch.sex = "man";
   ch.act.type = "pirate";
   ch.location = "Turks";
   ch.location.group = "reload";
   ch.location.locator = "reload1_2";
   ch.nation = PIRATE;
   ch.rank    = 1;
   ch.reputation = "65";
   ch.experience = "0";
   ch.skill.Leadership = "6";
   ch.skill.Fencing = "9";
   ch.skill.Sailing = "1";
   ch.skill.Accuracy = "9";
   ch.skill.Cannons = "7";
   ch.skill.Grappling = "1";
   ch.skill.Repair = "1";
   ch.skill.Defence = "4";
   ch.skill.Commerce = "1";
   ch.skill.Sneak = "1";
   ch.money = "10";
   ch.money.quest = "0";
   ch.quest.meeting = "0";
   ch.ship.type = SHIP_FORT_NAME; // PS
   ch.ship.pos.x = -488.099; // PB
   ch.ship.pos.z = -430.98; // PB
   ch.ship.crew.quantity = 500;
   ch.Fort.Cannons.Charge.Type = GOOD_BOMBS;
   // KNB -->
   if(USE_REAL_CANNONS)
   {
       ch.Fort.Cannons.Type.1 = CANNON_TYPE_LONG_LBS42;
       ch.Fort.Cannons.Type.2 = CANNON_TYPE_CARRONADE_LBS68;
   }
   else
   {
       ch.Fort.Cannons.Type.1 = CANNON_TYPE_CULVERINE_LBS24;
       ch.Fort.Cannons.Type.2 = CANNON_TYPE_CANNON_LBS32;
   }
   ch.Fort.Cannons.Type.1.Quantity = 6; // KK
   ch.Fort.Cannons.Type.2.Quantity = 14; // KK
   // KNB <--
   LAi_SetHP(ch, 100.0, 100.0);
   // RM -->
   ch.town = "Grand Turk";
   // RM <--
   AddGameCharacter(n, ch);
 
Is it not the other way round?
Yes.
This means fort commanders must have "Flags.Pirate" attributes assigned if they are to display Pirate flags.
I'll try to add some code: if they don't have those attributes - show a default flag.
Also as I mentioned earlier we can only choose from pirate flags from the current period. Not so many.
So pirate flags certainly doesn't work like personal flags.
 
Also as I mentioned earlier we can only choose from pirate flags from the current period. Not so many.
So pirate flags certainly doesn't work like personal flags.
That's probably because non-pirate forts do use period-dependent flags.
I think the code is mixing things to, since pirate flags aren't supposed to consider period at all.
 
I'll try to add some code: if they don't have those attributes - show a default flag.
Also as I mentioned earlier we can only choose from pirate flags from the current period. Not so many.
So pirate flags certainly doesn't work like personal flags.

Pirate flags aren't limited by period. Fort flags are, and the normal version of the game will use the pirate flag from the fort flag textures, which is the Rackham one in all periods. But the pirate flags which you choose for your ship, and which are governed by the "Flags.Pirate" attributes, shouldn't have anything to do with periods.
 
Not for ships but I tested pirate flags for forts and could only use those from the current period texture file.
I'll make a few more attempts then I'll leave it as it is.

Maybe I'll try to set PirateOveride to false when I arrive to a certain shore and hoist Pyle's red pirate flag there.
And reset it to true when leaving. Only in WoodesRogers. The red Pyle pirate flag is one of those from the "right" period.
 
Back
Top