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

Drastically reduce chance of Pirate encounter in friendly ports

Tingyun

Corsair
Storm Modder
A large percentage of the time when I enter my ship in a friendly (English) port, or sail into a friendly port from the worldmap, there is a pirate ship or two right there sitting in the harbour.

And the fort blasts it to pieces in a few minutes.

During my recent round of tests, I saw this happen 6 or 7 times. Once, the pirate ship even surrendered under the fort's onslaught, and I sailed up and the captain after losing a swordfight died and I got the ship. No boarding risk or lost sailors.

During that test, I had a tier 7 ship, and through it I was upgrade to a good tier 5 entirely by the stupid pirates sitting there and getting blasted by a fort. The game mechanics of this are all wrong. Even when they get blown up, I could pick up some of their cargo, and the chance of getting a ship capture that is overpowered for the player is very high, through no effort or good playing of their own. Honestly, I wonder if the easiest place to farm pirate ships is just entering and exiting a port.

And from a realism perspective, it makes no sense. If a pirate ship were sitting there in the harbour, the fort wouldn't wait until the second I boarded my ship to destroy it. And the pirate ship wouldn't sail up to the fort anyway.

Sea Dog difficulty, lvl 14 player character, this happened over half the time I went from town to deck of my ship, or went to a friendly town port.

Sidenote, when the pirates got blown up, usually the fort command would get the XP according to the log, but once it simultanously awarded the XP to both the fort commander and "God", saying it was killed by the hand of god. How much XP does God take to level up? ;)

Suggestion: Block all pirate ship encounters in ports with forts, 0% chance makes sense. Pirates shouldn't randomly commit suicides against forts. Even the "pirates raid town" ship log entry says the pirates snuck around to avoid the fort, they aren't going to risk getting in a shooting match with it, and anytime they go after the player in a port the fort is going to kill them.
 
Last edited:
Just finished playing and while I was attacking a French town I could see pirates nearby (I also took some cool screenshots!).

I think they shouldn't appear near towns if their ships aren't strong enough (tier 2 and 1 only). Two tier 1 pirate ships may even destroy the fort if lucky (the AI doens't work so good vs forts) so that could be interesting but what pirate has tier 1 ships? Only the pirates from the PiratesAhoy! community, of course :pirates

Maybe removing them completely is the best way of dealing with it.
 
These Coast Raider ships are put in place when you enter 3D sailing mode (as the sea scene very simply doesn't exist unless you're there yourself).
They're placed at a randomly chosen position and this process has no clue if that position is near a fort or town.

Removing pirate ships from such encounters means you can only find Pirates on the worldmap or during DirectSail. Doesn't sound ideal to me.
But if I recall, there is already in InternalSettings.h an option you can use to change the ratio between pirate and non pirate Coast Raiders.
 
Hi Pieter,

There is a value in the InternalSettings.h called "COASTRAIDER_CHANCE", it's a float value but it affects all types of ships, not only pirates but merchants too. By default it's 0.2 and the minimum is 0.1 for minimum pirates or 0.0 for no ships at all.

That's a way of dealing with it but I also don't like the idea of finding Pirates only on the worldmap or DirectSail so I guess that's an engine limitation.
 
Not so much the engine. It probably could be avoided; it would just require a substantial rewrite of the relevant code.
I can't really think of any quick fixes or simple solutions though.
So this is one more for the list of things that are in theory not impossible, if only there were somebody to make it happen.
 
Pieter, that makes sense.

I take it it would also be difficult to tell Pirates ships AI to run away from forts (or more generally, tell ships of hostile kingdoms to run away as well, as coastal raiders shouldn't be attacking forts)? It would be pretty cool if they would hang out out of range of the fort, attacking merchant ships or players if they try to leave, or even just running completely away would be better than getting blasted. But I imagine AI changes are difficult as well?
 
Last edited:
Actually, that is not impossible.
I wonder how best to approach it though.
Do you ever see AI ships attacking forts? If so, it might be quite doable to stop at least that and make them run away.
For that, I do at least have a faint idea on how to tackle that....
 
Hi Pieter,

Usually they seem to attack me or other friendly ships, but given I spawn in the harbor that means they sail directly towards the fort, and start getting blasted, and they continue heading towards me even as the fort is raining fire on them. The only time I have seen them successfully run is when they surrendered first.

I think I have also seen them begin firing on the fort after being attacked by it, but I am not sure of that part. @Eskhol do you know better how they behave?
 
That's tricky. They'd have to continuously check their distance to hostile forts then.
Not technically impossible though, since I managed to get that particular distance calculation working correctly at last a while back.
 
I haven't got any ship to surrender but one so in my case they usually don't surrender (but they spawned far enough to be able to escape almost every single time and most of the time they have small ships). One time they were attacking the fort but I think it was because they couldn't find a good way to escape so while moving they were also shooting it and crashing into the rocks :rofl
Another time instead of pirates it was French or Spanish and they almost destroyed the fort but I don't know if that would've happend if the same ships were pirates.

Maybe if we make pirates have bigger ships they would actually attack the fort if their ships are strong enough. We can do that on the "InternalSettings.h", right?
 
Eskhol, there is a setting to increase the max tier of pirate ships, but it isn't exactly realistic to have them often running around in giant ships or directly attacking forts. ;) I think the idea here is to get them to preserve themselves and hunt for vulnerable targets outside ports, not regularly launch full scale assaults.

So Eskhol from your post you can confirm they do fire on the forts--That is what I think I saw as well.

Thanks Pieter for considering implementing a solution--it looks like it will be difficult, but if it can be done at some point in the future, I think it would really help the coastal raiders experience. Of course I understand there are a lot of different priorities you have to balance. :)
 
It's not realistic at all, I think it's set to tier 4 so they won't get anything too crazy but that may be the reason they don't usually attack and just surrender. The same happens if some pirates attack you in the worldmap and then they realize you have 4 tier 1 ships and they have 2 sloops. They just start running away as soon as they see you! :rofl
 
The difficulty to change the AI behaviour is not too huge. However, it does require careful consideration and a fair bit of time.
I don't imagine I'll be able to afford doing any substantial work on this myself for the foreseeable future.
But since I do have a fair idea on how to do it, I'd be happy to support anyone interested in giving it a try.
The relevant file is PROGRAM\Screwface_functions.c which contains sea AI functions being called every minute in the game.

I strongly recommend against touching the maximum ship tier for Pirates.
While that setting does exist, it won't do you much good because the ship encounter chances are set up in such a way that it probably won't work if you increase that value.
 
I have just basic knowledge of programming so I don't think I can help but I will take a look at the file anyways. :)
 
Thanks Pieter, I certainly understand you have a lot of different things to work on and have to prioritize. I hope someone picks up this specific issue, but either way, you guys have created the most addictive and fun gaming experience I have seen in a long time, and I'm excited about all the different work you are doing to continue to improve it! :)
 
I recommend you both have at least a look at that file to see if you can understand any of it.
It isn't actually the most complex code in the game and there are some explanatory comments in there, so you might just get father than you'd think! :onya

If you have any specific questions on what's what, you can always ask and I'll do what I can to explain.
 
To give you an extra clue:
I imagine what needs doing is to loop through all ships in the scene (probably already being done somewhere in that file, so you can use that as example) and if any of them is a hostile fort within a certain range, then assign the "runaway" task (you'll see this being done in other situations already too).

If I recall correctly, the main thing that would be different is that ALL targets should be considered, so including forts, instead of just the nearest hostile ship (as is currently the case, I think).
 
I was able to find everything Pieter mentioned, and I am starting to have an idea of how some of these things might work. But I think a great deal of this is going over my head. ;) Here are some parts I pulled out for my future study:

Here seems to be the part that makes pirates run away from warships as long as their group is weaker. However, as Pieter says, it seems to be measuring the relevant group by looking to one specific hostile ship.


// To check if chr1 ship is stronger than chr2 ship
bool Ship_power_inf(ref chr1, ref chr2)
{
ref rgroup = Group_GetGroupByID(GetGroupIDFromCharacter(chr1));
ref rgroup2 = Group_GetGroupByID(GetGroupIDFromCharacter(chr2));
bool result = false;

if(GetCannonCurQuantity(chr1)<=0) {chr1.runaway = "1"; return true;}
if(!CheckAttribute(chr1,"Fantomtype")) return true;

// PIRATES REACTIONS
if(CheckAttribute(chr1,"fantomtype") && chr1.fantomtype == "pirate")
{
// THEY DON'T LIKE WAR SHIPS BUT ATTACK THEM IF THEY HAVE SUPERIOR POWER
if(CheckAttribute(chr2,"fantomtype") && chr2.fantomtype == "war" || chr2.index == GetMainCharacterIndex())
{
//LogIt("Power rgroup : " + Group_GetPowerHP_R(rGroup));
//LogIt("Power rgroup2 : " + Group_GetPowerHP_R(rGroup2));
if(Group_GetPowerHP_R(rGroup) >= Group_GetPowerHP_R(rGroup2))
{
//LogIt("I'm stronger");
return true;
}
else
{
//LogIt("number ships rgroup : " + Group_GetCharactersNumR(rGroup));
//LogIt("number ships rgroup2 : " + Group_GetCharactersNumR(rGroup2));
if(Group_GetCharactersNumR(rGroup) >= Group_GetCharactersNumR(rGroup2) && GetCharacterShipClass(chr1) <= GetCharacterShipClass(chr2))
{
//LogIt("j'attaque");
return true;
}
else
{
// They run away
chr1.runaway = "1";
if(Ship_GetDistance2D(chr1, chr2) < 200 && GetCannonCurQuantity(chr1)>2 && GetCargoGoods(chr1,GOOD_GUNPOWDER)>0)
{
if(GetCargoGoods(chr1,GOOD_BALLS)>0 || GetCargoGoods(chr1,GOOD_KNIPPELS)>0) // stop running and defend if a bigger enemy is too close
{
DeleteAttribute(chr1,"runaway");
}
}
return true;
}
}
}
else
{
// TRADE SHIPS : They attack
if(GetCharacterShipClass(chr2) == 1)
{
// Pirates don't like big escorts
chr1.runaway = "1";
return true;
}
else
{
return true;
}
}
}





Here's the warship part, which seems to be comparing group strengths in deciding to attack or run away:

// WAR SHIPS REACTIONS
if(CheckAttribute(chr1,"fantomtype") && chr1.fantomtype == "war")
{
if(CheckAttribute(chr2,"fantomtype") && chr2.fantomtype == "war" || chr2.index == GetMainCharacterIndex())
{
if(Group_GetPowerHP_R(rGroup) >= Group_GetPowerHP_R(rGroup2))
{
return true;
}
else
{
if(Group_GetCharactersNumR(rGroup) >= Group_GetCharactersNumR(rGroup2) && GetCharacterShipClass(chr1) <= GetCharacterShipClass(chr2))
{
return true;
}
else
{
// They run away
chr1.runaway = "1";
if(Ship_GetDistance2D(chr1, chr2) < 200 && GetCannonCurQuantity(chr1)>2 && GetCargoGoods(chr1,GOOD_GUNPOWDER)>0)
{
if(GetCargoGoods(chr1,GOOD_BALLS)>0 || GetCargoGoods(chr1,GOOD_KNIPPELS)>0) // stop running and defend if a bigger enemy is too close
{
DeleteAttribute(chr1,"runaway");
}
}
return true;
}
}
}
else
{
// TRADE SHIPS OR PIRATES : They attack
return true;
}
}

if( CheckAttribute(chr1,"Fantomtype") && chr1.fantomtype == "trade") return true; // trade ship have other reactions

return false;
}




Here's a part that seems to cycle through multiple groups in visibility range:

for (i=0; i<MAX_SHIP_GROUPS; i++)
{
rGroup = Group_GetGroupByIndex(i);
if(CheckAttribute(rGroup,"AlreadyLoaded"))
{
//LogIt(" " + rgroup.id + " ");

if (!CheckAttribute(rGroup, "id")) { continue; }
if (!CheckAttribute(rGroup, "location")) { continue; }
if (rGroup.location != PChar.location) { continue; }
achr = Group_GetGroupCommanderR(rGroup);

if(CheckAttribute(achr,"surrendered") || CharacterIsDead(achr)){continue;} //Group_UpdateGroup(achr);continue;}
if(!Checkattribute(achr,"index")){continue;}
if(GetNationRelation(sti(achr.nation), sti(chr.nation)) == RELATION_ENEMY)
{
//achr = Group_GetGroupCommander(rGroup.id);
enemydist = Ship_GetDistance2D(achr, chr);
if(Whr_IsNight() && HasCharacterShipAttribute(achr, "night_stealth")) effective_range = visibility_range / 2; // PB: Black Pearl stealth at night
if(enemydist < effective_range && Ship_power_inf(chr,achr))
{
//LogIt(" " + chr.Ship.Pos.x + " ");
//LogIt(" Enemy distance : " + enemydist + " ");
if(enemydist < memoire || place == -1)
{
if(place == -1 || GetShipSkill(chr, Skill_LEADERSHIP)>4) // lower captains are Stubborn
{
place = achr.index;
memoire = enemydist;
}
}
}
}
}
else
{
if(CheckAttribute(rGroup, "id"))
{
achr = Group_GetGroupCommanderR(rGroup);
if(CheckAttribute(achr, "id") && HasSubStr(achr.id, "fenc_"))
{
achr = Group_GetGroupCommanderR(rGroup);
if(CheckAttribute(achr,"surrendered") || CharacterIsDead(achr)){continue;}
if(!Checkattribute(achr,"index")){continue;}
if(GetNationRelation(sti(achr.nation), sti(chr.nation)) == RELATION_ENEMY)
{
enemydist = Ship_GetDistance2D(achr, chr);
if(enemydist < visibility_range && Ship_power_inf(chr,achr))
{
if(enemydist < memoire || place == -1)
{
if(place == -1 || GetShipSkill(chr, SKILL_LEADERSHIP)>4) //lower captains are Stubborn
{
place = achr.index;
memoire = enemydist;
}
}
}
}
}
}
}
}






Here's some interesting parts that seem to be doing something with Forts and pirates (but I don't understand what):



bool CheckForPirateException(ref chr)
{
bool IsFort = !bSeaActive;
IsFort = IsFort || GetAttribute(chr, "ship.type") == SHIP_FORT_NAME;
bool PirateException = false;
if (IsFort)
{
PirateException = true;
if(GetCurrentFlag() != PIRATE) PirateException = false;
if(GetNationRelation2MainCharacter(PIRATE) == RELATION_ENEMY) PirateException = false;
if(GetFortRelationToPirates(chr) == RELATION_ENEMY) PirateException = false;
}
return PirateException;
}



This part seems to check all ships for something, which might be what we need:


bool CheckAllShips(string type, bool initialize)
{
int i, shipidx, num;
aref shipattr;
string shipstr;
ref chr;
float ship_range = 0.0;
float visibility_range = 0.0;
ref PChar = GetMainCharacter();

@Eskhol , you said you had some basic programming background, so you probably understand what is going on here much better. :)
 
Last edited:
Back
Top