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

Mod Release Build 14 Gamma Version [Last update: 12th January 2024]

@Grey Roger, do you know what happened here?
Code:
//    bool NoLandGiven = ProfessionalNavyNation() != UNKNOWN_NATION && curRank < 7;
    bool NoLandGiven = curRank < 7;    // GR: no land for navy OR privateers until you are landed gentry    if(NoLandGiven || iNation == PIRATE)
Especially that if-section at the end of that comment?
Shouldn't that 'iNation == PIRATE' be used somewhere in there?
Otherwise, wouldn't the Pirates give out land rewards too?
That's not supposed to be... :confused:
 
@Grey Roger, do you know what happened here?
Code:
//    bool NoLandGiven = ProfessionalNavyNation() != UNKNOWN_NATION && curRank < 7;
    bool NoLandGiven = curRank < 7;    // GR: no land for navy OR privateers until you are landed gentry    if(NoLandGiven || iNation == PIRATE)
Especially that if-section at the end of that comment?
Shouldn't that 'iNation == PIRATE' be used somewhere in there?
Otherwise, wouldn't the Pirates give out land rewards too?
That's not supposed to be... :confused:
Where is that? It looks as though someone has goofed while editing.

If it's in "PROGRAM\Characters\CharacterUtilite.c", it should be:
Code:
//    bool NoLandGiven = ProfessionalNavyNation() != UNKNOWN_NATION && curRank < 7;
    bool NoLandGiven = curRank < 7;    // GR: no land for navy OR privateers until you are landed gentry
    string title, text;

    Preprocessor_Add("nationdesc", XI_ConvertString(GetNationDescByType(iNation)));
    Preprocessor_Add("nationname", XI_ConvertString(GetNationNameByType(iNation)));
    Preprocessor_Add("rank", XI_ConvertString(GetRankNameDirect(char, iNation, currank)));
    Preprocessor_Add("govname", GetMySimpleName(gov));
    Preprocessor_Add("newland", "" + curRank*LAND_PER_RANK);
    title = GetTranslatedLog("Promoted to #snationdesc# #srank#");
    text = GetTranslatedLog("My dedication and faithful service for #snationname# have earned me the rank of #srank#.")
    if(!NoLandGiven && iNation != PIRATE)
And that is what is in the October 2023 update.
 
I caught a really dumb error, with apparently the wrong character IDs being used.
See attached for a fix.
As bonus, this random captain potential soldier raid will now only trigger AFTER the dialog.
So no more getting cut down while you're still reading.

Where is that? It looks as though someone has goofed while editing.

If it's in "PROGRAM\Characters\CharacterUtilite.c", it should be:
Code:
//    bool NoLandGiven = ProfessionalNavyNation() != UNKNOWN_NATION && curRank < 7;
    bool NoLandGiven = curRank < 7;    // GR: no land for navy OR privateers until you are landed gentry
    string title, text;

    Preprocessor_Add("nationdesc", XI_ConvertString(GetNationDescByType(iNation)));
    Preprocessor_Add("nationname", XI_ConvertString(GetNationNameByType(iNation)));
    Preprocessor_Add("rank", XI_ConvertString(GetRankNameDirect(char, iNation, currank)));
    Preprocessor_Add("govname", GetMySimpleName(gov));
    Preprocessor_Add("newland", "" + curRank*LAND_PER_RANK);
    title = GetTranslatedLog("Promoted to #snationdesc# #srank#");
    text = GetTranslatedLog("My dedication and faithful service for #snationname# have earned me the rank of #srank#.")
    if(!NoLandGiven && iNation != PIRATE)
And that is what is in the October 2023 update.
But... what is to prevent the Pirates from giving out land then??
I would think it should be like this:
Code:
//    bool NoLandGiven = ProfessionalNavyNation() != UNKNOWN_NATION && curRank < 7;
    bool NoLandGiven = curRank < 7;    // GR: no land for navy OR privateers until you are landed gentry
    NoLandGiven = NoLandGiven && iNation != PIRATE; // PB: Pirates have no land to give
 

Attachments

  • Dialog_func.c
    106.7 KB · Views: 21
  • Random_captains_sit_tavern_dialog.c
    19.4 KB · Views: 21
Doesn't that make him too easy to kill? He has a good melee weapon and good stats, though he could probably do with a "questchar" attribute so that levelling doesn't wreck those stats. So you just keep your distance and lob a poisoned throwing knife at him, rather than having to close and hit him with a poisoned sword.

For the record, I was the one who complained on Discord because I found out that only the Borgiablade worked. I was absolutely convinced that the poisoned throwing knife would also do the job, since it mentions a frog in its description. And it was the poison from a frog on a blade that did him in.
Personally I don't see why it's necessary to limit his weakness to one single weapon you have to be really lucky to find in the first place. I would agree with the "too easy to kill"-sentiment if he would die in one hit from any poisoned weapon. But they just remove his invulnerability, you still have to defeat him in a fight.

Instead, I suggest something else.

For me, the Sword of Triton is a classic gamebreaker. Not only is it very strong, it also has one very useful, and one frankly overpowered ability (and doesn't seem to decrease in quality?). In my opinion it serves best as an endgame-item, when you're already conquering the Carribbean, can take on entire fleets by yourself, and seek a new challenge, outside of just selecting a higher difficulty. The kind of weapon you would receive after completing a brutally difficult bonus-dungeon in an RPG, which you would need a high level, specifically set-up party members, and high-end equipment to beat.
Blackbeard however just goes down in seconds if four people gang up on him, especially if you are high-level yourself. Thus I wonder if it would help if Blackbeard was a ridiculously high level (80?), had a gold cuirass, and was immune to getting stunned. And you had to fight him alone.
 
I caught a really dumb error, with apparently the wrong character IDs being used.
See attached for a fix.
As bonus, this random captain potential soldier raid will now only trigger AFTER the dialog.
So no more getting cut down while you're still reading.
I don't see the problem with "Dialog_func.c". So long as it's using the same character ID's throughout, does it matter whether it uses "Coastal_Captain01" or "Enemy_Captain01"? Both characters are defined in "CommonQuest.c". And I've certainly had to face duels at sea if I talked to one of these hostile captains in a tavern.

But... what is to prevent the Pirates from giving out land then??

I would think it should be like this:
Code:
//    bool NoLandGiven = ProfessionalNavyNation() != UNKNOWN_NATION && curRank < 7;
    bool NoLandGiven = curRank < 7;    // GR: no land for navy OR privateers until you are landed gentry
    NoLandGiven = NoLandGiven && iNation != PIRATE; // PB: Pirates have no land to give
What prevents pirates from giving out land is this:
Code:
    if(!NoLandGiven && iNation != PIRATE)
    {
        AddLandToCharacter(&char, Locations[FindLocation(gov.location)].island, iNation, curRank*LAND_PER_RANK); // KK
        text = text + " " + GetTranslatedLog("The #snationdesc# governor #sgovname# awarded me with the title and #snewland# acres of land.");
    }
'NoLandGiven' checks that you're ineligible for land due to rank. Then that condition adds the check that the character doing the promoting isn't a pirate.
 
I don't see the problem with "Dialog_func.c". So long as it's using the same character ID's throughout, does it matter whether it uses "Coastal_Captain01" or "Enemy_Captain01"? Both characters are defined in "CommonQuest.c". And I've certainly had to face duels at sea if I talked to one of these hostile captains in a tavern.
Sure, the duels work.
But it's supposed to be a duel with the same character you encountered.
And that is where it fails.
He gets a random name and model, which isn't intentional.

What prevents pirates from giving out land is this:
Code:
if(!NoLandGiven && iNation != PIRATE)
{
AddLandToCharacter(&char, Locations[FindLocation(gov.location)].island, iNation, curRank*LAND_PER_RANK); // KK
text = text + " " + GetTranslatedLog("The #snationdesc# governor #sgovname# awarded me with the title and #snewland# acres of land.");
}
'NoLandGiven' checks that you're ineligible for land due to rank. Then that condition adds the check that the character doing the promoting isn't a pirate.
AGH, I must've been BLIND! :facepalm
'bool NoLandGiven' now barely serves a purpose.
Might as well just do 'if(curRank >= 7 && iNation != PIRATE)' and be done with it.
But either way.... doesn't make a difference.
My bad!
 
Sure, the duels work.
But it's supposed to be a duel with the same character you encountered.
And that is where it fails.
He gets a random name and model, which isn't intentional.
Ah, I see. At the top of 'SetCoastalEnemy' is this:
Code:
ref rCap1 = CharacterFromID("Coastal_Captain01");
Then the various attributes passed from "Random_captains_sit_tavern_dialog.c" are applied to rCap1. So a simpler fix, instead of changing everything further down to "Coastal_Captain", would be to change that one line:
Code:
ref rCap1 = CharacterFromID("Enemy_Captain01");
And it doesn't matter which character is used for the second captain who appears if you have a companion or you're high level, because you never saw him in the tavern.
 
Ah, I see. At the top of 'SetCoastalEnemy' is this:
Code:
ref rCap1 = CharacterFromID("Coastal_Captain01");
Then the various attributes passed from "Random_captains_sit_tavern_dialog.c" are applied to rCap1. So a simpler fix, instead of changing everything further down to "Coastal_Captain", would be to change that one line:
Code:
ref rCap1 = CharacterFromID("Enemy_Captain01");
And it doesn't matter which character is used for the second captain who appears if you have a companion or you're high level, because you never saw him in the tavern.
But this is what those "Coastal_Captain" character IDs are for.
As it is, we might as well remove them altogether.
I don't know what will happen when mixing with the "Enemy_Captain" ones.
I'd figure those are other IDs for a reason.
 
@Grey Roger, please find attached all my proposed updates.
Hope you can check for validity.
It took quite some doing, because you wanted all those tavern time limits modified.
 

Attachments

  • PB_PROGRAM.7z
    6.2 MB · Views: 24
@Grey Roger, please find attached all my proposed updates.
Hope you can check for validity.
It took quite some doing, because you wanted all those tavern time limits modified.
Checking will also take some time because you have uploaded what looks like the entire "PROGRAM" folder, not just the stuff you updated!

A couple of things I've already noticed:
"PROGRAM\Storyline\standard\quests\quests_reaction.c", case "Story_VoyageToKhaelRoaBegan": you added 'TranslateString to 'SetTownName("Greenford", TranslateString("","Bridgetown"));' but that is not needed because 'FindTownName' already translates town names for display.

"PROGRAM\Loc_ai\types\LAi_stay.c", function 'LAi_type_stay_CharacterUpdate': presumably you have not tested this. I did, and the game crashed because your new lines to check the "talker" attribute also check that PChar can dialog, but there's no declaration for PChar. After I added 'ref PChar = GetMainCharacter();' to the function, the game did not crash.

Tavern time limits are still incorrect, they should be checking for '>= 22.0' instead of '> 22.0'.

Any changes to "Assassin", "Bartolomeu", "Woodes Rogers" and "Goldbug" must be checked with their respective authors. Translations are handled by their respective translators and I'll stick with the most recent files I got from them.

Any file which looks as though the only differences are minor formatting changes won't be copied. I've been wasting a lot of time looking for differences only to find that the differences are a few spaces being deleted!
 
Checking will also take some time because you have uploaded what looks like the entire "PROGRAM" folder, not just the stuff you updated!
You can hide identical files with WinMerge.

A couple of things I've already noticed:
"PROGRAM\Storyline\standard\quests\quests_reaction.c", case "Story_VoyageToKhaelRoaBegan": you added 'TranslateString to 'SetTownName("Greenford", TranslateString("","Bridgetown"));' but that is not needed because 'FindTownName' already translates town names for display.
Ah. :facepalm

"PROGRAM\Loc_ai\types\LAi_stay.c", function 'LAi_type_stay_CharacterUpdate': presumably you have not tested this. I did, and the game crashed because your new lines to check the "talker" attribute also check that PChar can dialog, but there's no declaration for PChar. After I added 'ref PChar = GetMainCharacter();' to the function, the game did not crash.
I tested it on the Maelstrom edition, where it worked.
But then, that one had a global PChar definition.
Must admit that did make me suspicious...

Tavern time limits are still incorrect, they should be checking for '>= 22.0' instead of '> 22.0'.
I think that makes zero difference.
But do as you wish.

ny file which looks as though the only differences are minor formatting changes won't be copied. I've been wasting a lot of time looking for differences only to find that the differences are a few spaces being deleted!
I do so hate messily formatted files!
Wished there was a way of deleting excessive spaces automatically in all open files.
It's so ugly.
 
Any changes to "Assassin", "Bartolomeu", "Woodes Rogers" and "Goldbug" must be checked with their respective authors.
Certainly the Assassin HP change is approved by @Bartolomeu o Portugues.

Translations are handled by their respective translators and I'll stick with the most recent files I got from them.
Don't remember making much changes to those.
Though do recall the Polish changed file looked suspect.
 
The first update of 2024 is now out.
https://piratesahoy.bowengames.com/potc/Grey Roger/post_1Jan_updates_120124.zip

A lot more translating has been done by @AkrimalS and @Homo eructus, and there's now the beginning of a French translation by @guigui0017.
A new shader module by @tuan16 improves the reflective appearance of the sea, especially at sunset.
@Jack Rackham continues to make improvements to the "Woodes Rogers" and "Goldbug" stories, with added details to some locations and a fix for some special quest items appearing excessively shiny.
@Pieter Boelen has been doing a lot of tweaking, including a fix for dialog with a hostile captain in a tavern - if the captain calls an ambush, it won't happen until you finish talking with him.
And there's a new location imported from TEHO, a big mine. You'll see it if you play the "Ardent" storyline as it's now used for the crew rescue scene early in the story, and other modders may make use of it in future developments.
 

Attachments

  • fixes.txt
    24.5 KB · Views: 37
But this is what those "Coastal_Captain" character IDs are for.
As it is, we might as well remove them altogether.
I don't know what will happen when mixing with the "Enemy_Captain" ones.
I'd figure those are other IDs for a reason.
Indeed they are. The "Coastal_Captain" ID's are for coastguard ships which may appear if you've been smuggling. So is sea AI group "Coastal_Guards". At a guess, whoever wrote 'SetCoastalEnemy' realised that there could be a problem if you've been smuggling and talking to random tavern captains, changed "Coastal" to "Enemy", but didn't make a complete job of it.
 
By clicking on that link. ;) Then you need to unzip it - this is just a simple zip file, not a .exe which does anything automatically. But its folder structure is the same as the game's, so you can either unzip it straight into the game's top level installation folder, or unzip it somewhere completely different and then copy the whole lot straight to the game folder.
Aye aye, thank you. Took me a while to get used to modding again - been quite some time :)
 
Made some very small changes, improved the ribbles a little bit. it's still the same sea, but just a little bit better.

Edit: Sorry, for frequent updates, hope that is not too much of a hastle... Changed the file and made an even better sea, now even more beautiful!
 

Attachments

  • ATIShaders.txt
    4.5 KB · Views: 15
Last edited:
Indeed they are. The "Coastal_Captain" ID's are for coastguard ships which may appear if you've been smuggling. So is sea AI group "Coastal_Guards". At a guess, whoever wrote 'SetCoastalEnemy' realised that there could be a problem if you've been smuggling and talking to random tavern captains, changed "Coastal" to "Enemy", but didn't make a complete job of it.
In that case, how about changing it so that up to THREE enemy ships may appear?
Because there are three "Enemy_Captain" IDs...
 
In that case, how about changing it so that up to THREE enemy ships may appear?
Because there are three "Enemy_Captain" IDs...
Check "PROGRAM\Characters\init\CommonQuest.c" again. There are "Coastal_Captain01", "Coastal_Captain02" and "Coastal_Captain03"; and function 'CreateCoastGuardPatrol()' in "PROGRAM\smuggling.c" does indeed allow three ships to appear if you have at least two companion ships or you're at least level 9. But there are only "Enemy_Captain01" and "Enemy_Captain02".

Besides, if you sneaked into an enemy port and met an enemy captain in the tavern, those ships are the least of your worries. You're under a false flag friendly to the port. If you keep flying it, you'll be branded a pirate if you fight the enemy captain. If you hoist a flag hostile to the captain, you'll be fighting him, any other ships in the area who don't like your new flag, and the fort.
 
Why is this line gone from NK.c?
Code:
if(HasSubStr(tempstring, "petros"))                    CursedSails = "sail_torn_red_plain.tga";

If France needs an Emissary, shouldn't they also get a Tailor?
Code:
        case PERIOD_EARLY_EXPLORERS:
            ChangeCharacterAddressGroup(characterFromID("English Emissary"), "Tortuga_Townhall",  "goto","goto2");
            ChangeCharacterAddressGroup(characterFromID("Dutch Emissary"),   "Tortuga_Townhall",  "Sit", "Sit1");
            ChangeCharacterAddressGroup(characterFromID("French Emissary"),  "Tortuga_Townhall",  "goto", "goto6");
            ChangeCharacterAddressGroup(characterFromID("English Tailor"),   "Tortuga_tailorsShop", "goto","stay2");
            ChangeCharacterAddressGroup(characterFromID("Dutch Tailor"),     "Tortuga_tailorsShop", "goto","stay3");

How does this help to fix shiny items?
Code:
                //JRH fix for shiny items -->
                if(sti(GetStorylineVar(FindCurrentStoryline(), "WR_PUZZLES")) > 0 || sti(GetStorylineVar(FindCurrentStoryline(), "BUG_PUZZLES")) > 0)
                {
                    if(newitm == "pistol1" || newitm == "pistol7" || newitm == "pistol6" || newitm == "pistol3" || newitm == "pistol8"
                    || newitm == "pistol4" || newitm == "pistol27" || newitm == "Longrifle_H" || newitm == "pistolcollier" || newitm == "pistolmketB") return;
                }
                //JRH <--

Something here doesn't look right:
Code:
    //Generate the Captain
    //sld = LAi_CreateFantomCharacter(false, 0, true, true, 0.75, GetRandomModelForTypeNation(true, "Land_Officers", GetSmugglingNation()), group, locator);
    sld = LAi_CreateFantomCharacterExOt(false, 0, true, OFFIC_TYPE_GUARD, GetRandomRank(true, OFFIC_TYPE_GUARD, (4-GetDifficulty())), true, 0.75, GetRandomModelForTypeNation(true, "Land_Officers", GetSmugglingNation()), group, locator);
    sld.Dialog.Filename = "Coastal Guards_dialog.c";
    sld.Dialog.CurrentNode = "First time";
    Pchar.quest.contraband.SoldierIDX1 = sld.index;
    LAi_SetActorType(sld);
    LAi_group_MoveCharacter(sld, "CoastalGuards");
    LAi_ActorDialog(sld, Pchar, "", 120, 0);
    //Generate the Guards
    for (int i = 2; i <= numguards; i++)
    {
        IDXname = "SoldierIDX"+i;
        //sld = LAi_CreateFantomCharacter(false, 0, true, true, 0.75, GetRandomModelForTypeNation(true, "Soldiers", GetSmugglingNation()), group, locator);
        sld = LAi_CreateFantomCharacterExOt(false, OFFIC_TYPE_GUARD, GetRandomRank(true, OFFIC_TYPE_GUARD, (4-GetDifficulty())), true, 0.75, GetRandomModelForTypeNation(true, "Soldiers", GetSmugglingNation()), group, locator);
Specifically, this line:
Code:
sld = LAi_CreateFantomCharacterExOt(false, 0, true, OFFIC_TYPE_GUARD, GetRandomRank(true, OFFIC_TYPE_GUARD, (4-GetDifficulty())), true, 0.75, GetRandomModelForTypeNation(true, "Land_Officers", GetSmugglingNation()), group, locator);
Because:
Code:
ref LAi_CreateFantomCharacterExOt(bool isfriend, string officertype, int rank, bool hasblade, float hasgun, string model, string group, string locator)
This doesn't have the 'int offset' parameter.

Why are the brothel enabled if-statements gone?
Code:
    // brothel
    if(IsBrothelEnabled())
    {
        curTable.l7.pic = FRP_BROTHEL; // MAXIMUS interface MOD
        curTable.l7.tex = FRT_BROTHEL; // MAXIMUS interface MOD
        curTable.l7.note = FRN_BROTHEL; // KK
        curTable.l7.location = "QC_brothel"; // MAXIMUS interface MOD
    }

For this:
Code:
bool SetUsedPotionIcons()
{
    aref arItm, ar, uiref;
    int i, itmIdx, nq;
    ref mc = GetMainCharacter();

    bool bUsed = false;
    int idLngFile = LanguageOpenFile("commands_name.txt");
Shouldn't there be an accompanying 'LanguageCloseFile(idLngFile);' at the end?

I don't know where those last 4 lines came from, but shouldn't they be kept?
Code:
                // default
                if (GetCurrentPeriod() < PERIOD_GOLDEN_AGE_OF_PIRACY)
                {
                    if(ENABLE_WEAPONSMOD)    GiveItem2Character(ch, "blade21+2");
                    else                    GiveItem2Character(ch, "blade21");
                    GiveItem2Character(ch, "bladekit");    
                }
                else
                {
                    if(ENABLE_WEAPONSMOD)    GiveItem2Character(ch, "blade27+1");
                    else                    GiveItem2Character(ch, "blade27");
                }
            }
            if (GetCurrentPeriod() >= PERIOD_GOLDEN_AGE_OF_PIRACY) GiveItem2Character(ch, "pistol1");
            else GiveItem2Character(ch, "pistol1a");
            GiveItem2Character(ch, "compass2");
            GiveItem2Character(ch, "clock1");
        break;
 
Last edited:
Back
Top