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

Linking cargo type to encounter type

Grey Roger

Sea Dog
Staff member
Administrator
Storm Modder
Where is the encounter type for ships you meet on the high seas generated? That is, things like "merchants", "merchants with light escort", "single merchant with heavy escort", etc. And where is the cargo to those ships assigned?

What I'd like to do, if it's possible, is to try to build some sort of link between the two. At the very least, unescorted merchants shouldn't be stuffed full of gold or silver. You'd expect anyone rich enough to be carrying that sort of cargo to also hire someone to escort him. Conversely, if three warships are escorting a single merchant then he's presumably carrying something important because the local admiral wouldn't assign such a force just to escort a consignment of linen. From the point of view of game balance, an unescorted merchant is easy prey for a novice pirate or privateer and if it's carrying a load of silver then that novice just became very rich, very early in the game. On the other hand if you take on a ship escorted by two frigates and a ship of the line, and survive, you ought to expect a hefty reward.
 
Have a look at the encounters folder. That's where those should be defined.

Normally cargo is completely independent from encounter type.
The exception is the Treasure Fleets that I hacked into the game.
You'll find some annoyingly messy booleans related to that in the SEA_AI folder.
That should at least point you in the direction of the related code you'd need to play around with. :doff
 
These treasure fleets, how can you recognize them?
Every cargo ship in them is fully laden with gold or silver?
They also have to be Spanish.

There might be a specific encounter description that applies, but I'm not sure about that anymore.
 
I can't stop thinking about this, it would do so much when playing a pirate and picking your targets :aar I've tried to follow the code and I think I understand how the encounters are generated, like how many ships of each type etc, but I dont know how you'd get that info to the function for generating cargo :eek:
 
I can't stop thinking about this, it would do so much when playing a pirate and picking your targets :aar I've tried to follow the code and I think I understand how the encounters are generated, like how many ships of each type etc, but I dont know how you'd get that info to the function for generating cargo :eek:
In a massively annoying way. Search the PROGRAM\SEA_AI folder.
I only did it for the "Treasure Fleets" and I really had to hack the system with a global boolean.
It works, but it's a super-messy solution. :facepalm
 
In a massively annoying way. Search the PROGRAM\SEA_AI folder.
I only did it for the "Treasure Fleets" and I really had to hack the system with a global boolean.
It works, but it's a super-messy solution. :facepalm
yeah, took a look now and its terrifying :shock

I feel like an idea is forming inspired by the treasure fleet bonanza however, but my head starts spinning when I try to plan it out so maybe it'll go better if I share it. it'll probably end up as messy or messier than the treasure fleets, but that's how it goes :modding

it seems Fantom_GenerateEncounter() is the heart of it all, and iNumWarShips and iNumMerchantShips are how many of each kinda ship are in an encounter. then cargo is distributed in Fantom_SetGoods(), could one maybe add different cargo to different "tiers" there, and somehow get encounter type, iNumWarShips and iNumMerchantShips, maybe class and rank too, to that function to influence what cargo goes to whom? it gets very confusing for me since there's a lot of "for" and "while" and returns in those functions, and I don't know what they do or how they are used yet :fiddle but would something like that be feasible tho?
 
There's definitely merit to your thinking, @DeathDaisy! :cheers

If you can check the EncounterType from within SetGoods, that might allow for a reasonable solution.
Create a whole lot of additional encounter types that each have their own type of cargo.
It can go into a 'switch' with the 'default' option being to do what it currently does.

Might that work...?
 
There's definitely merit to your thinking, @DeathDaisy! :cheers

If you can check the EncounterType from within SetGoods, that might allow for a reasonable solution.
Create a whole lot of additional encounter types that each have their own type of cargo.
It can go into a 'switch' with the 'default' option being to do what it currently does.

Might that work...?
It might! gonna try it out, see if I can even understand how and where to put the things to start with :p
 
would something like this work?

first some global ints to store enc type and number of ships
Code:
int iGetNumMerchantShips, iGetNumWarShips, iGetEncType;

int Fantom_GenerateEncounter(string sGroupName, int iEType, int iNation)
[other code]
   // Stores the results
   iGetNumMerchantShips = iNumMerchantShips;
   iGetNumWarShips = iNumWarShips;
   iGetEncType = iEType;
then set up an array of different tiered goods (I'm not usually a trader, so number of tiers and goods in each tier is subject for balancing :p)
Code:
string sGoodsTier1[14], sGoodsTier2[10], sGoodsTier3[2];
    int n;
    n = 0;
    n = AddStr2Array(&sGoodsTier1, n, "GOOD_WHEAT,GOOD_RUM,GOOD_FOOD,GOOD_TREATMENT,GOOD_PAPRIKA,GOOD_ALE,GOOD_LINEN,GOOD_FRUITS,GOOD_CLOTHES,GOOD_BRICKS,GOOD_OIL,GOOD_COTTON,GOOD_COPRA,GOOD_LEATHER");
    n = 0;
    n = AddStr2Array(&sGoodsTier2, n, "GOOD_CINNAMON,GOOD_CHOCOLATE,GOOD_COFFEE,GOOD_WINE,GOOD_SANDAL,GOOD_EBONY,GOOD_MAHOGANY,GOOD_SUGAR,GOOD_TOBACCO,GOOD_SILK");
    n = 0;
    n = AddStr2Array(&sGoodsTier3, n, "GOOD_GOLD,GOOD_SILVER");

the next part I'm not sure where to put, but this is my theory
Code:
for (int r=0;r<randGoods;r++)
    {
     
        switch(iGetEncType){
        case 0:
            Fantom_SetCharacterGoods(rFantom, &sGoodsTier1, makeint(iMultiply * rand(iRandMultiply * 3)) );
        break;
        case 1:
            if(rPhantom.PhantomType == "trade"){
            Fantom_SetCharacterGoods(rFantom, &sGoodsTier1, makeint(iMultiply * rand(rRandMultiply * 3)) );
            Fantom_SetCharacterGoods(rFantom, &sGoodsTier2, makeint(iMultiply * rand(rRandMultiply * 3)) );
            }
        break;
        [etc]
     
        //Fantom_SetCharacterGoods(rFantom, iStart + rand(GOODS_QUANTITY - iStart - 1), makeint(iMultiply * rand(iRandMultiply * 3)) );
    }
for different encounters you pull goods from the different tiers. later you can put variables for different number of ships, classes, char stats etc to affect the chance and amount of different tiers for different encounters. this far I mostly wanna see if the theory is sound/works at all :type1 not even sure the ints store the info I want correctly!
 
I've got to admit I'm quite tired right now, so I don't dare give any guarantees.
But at first impression, I think you've got the makings of a very sound plan there! :onya
 
Looks good ;)

One suggestion is if you look in goods.h you will see the goods are already intended to be set in descending value (per cwt). However they don't match the values in initGoods.c by now, so could possibly do with re-arranging to match the cost/weight ratio set there. [Not actually checked if there is any knock to that (apart from the order displayed in store) but I wouldn't expect so - generally just the #define is used].

Then rather than grouping the products in tiers as you suggest I think you just use a loop of requisite size when choosing goods for encounter type. So if you only want gold and silver it is for i=9 to 10, if a low value encounter say i=25 to 32. Would be easy to add random element too so if lucky might get -4 and loop would be 21 to 32.

One down side is that wheat and rum (=food and rum) would never be cargoes so you pirates and privateers would only get to plunder the ships rations and may have to BUY some ocassionally!!

PS I hope I am reading that correctly
 
At present, merchant ships rarely carry rum, and NPC ships in general rarely carry planks or sailcloth. So even I, who try to get everything "second-hand" where possible, generally need to buy those.

Perhaps group supplies (food, rum, planks, sailcloth, perhaps also medicaments) separately? That could lay the groundwork for another possible future mod, which is that trade goods (anything that isn't supplies) are locked for navy and privateer types. Ideally those should be auctioned off along with the prize ship, and be reduced by the same percentage as the ship itself. But you should be able to restock supplies from captured ships. (Nothing should be locked for pirates - they can help themselves to anything they like, providing a bit of an incentive to play pirate.)
 
That would be interesting, and an incentive for privateers to engage in smuggling on the side if they want to profit wholly of captured trade goods, but it would also take gameplay options away from navy playthroughs, a profession that already is quite restrictive in what you can do (I know, that's the point, it's the navy after all). More varied and specific navy gameplay options should be added before mpre generic options are removed, I think.
 
Last edited:
not at my comp right now, but gonna have a look at rearranging the goods.h later! could make it easier to add modifiers, maybe thinking like having GOOD_QUANTITY-iGetNumWarShips or something. worth considering!

if I remember the code right, I think wheat, rum and repair goods are actually never given as main cargo for traders. iStart is GOOD_PLANKS+1, the repair goods and ammo is generated separately. so that was an oversight in my arrays, but in my defense I was very tired :p
 
So this is the new goods order in goods.h, it is wildly different from before
Code:
#define GOODS_QUANTITY 33

#define GOOD_WHEAT        0    // PB: Rations first
#define GOOD_RUM        1    // PB: Rations first
#define GOOD_BALLS        2
#define GOOD_GRAPES        3
#define GOOD_KNIPPELS    4
#define GOOD_BOMBS        5

#define GOOD_GUNPOWDER    6
#define GOOD_SAILCLOTH    7
#define GOOD_PLANKS        8    // Numbers below are value index based on cost per cwt, multiply by GOODS_PRICE_SCALAR for actual cost/cwt
#define GOOD_GOLD       9   // 100
#define GOOD_SILVER     10  // 62
#define GOOD_COFFEE    11    // 14
#define GOOD_CINNAMON    12    // 11.5
#define GOOD_MAHOGANY        13    // 10.5
#define GOOD_EBONY        14 //10.3
#define GOOD_WINE            15 //10
#define GOOD_SANDAL        16    // 10
#define GOOD_PAPRIKA        17    // 9
#define GOOD_TREATMENT    18    // 9
#define GOOD_CHOCOLATE    19  // 9
#define GOOD_ALE    20    // 9
#define GOOD_SILK        21    // 8.5
#define GOOD_TOBACCO    22    // 7.75
#define GOOD_CLOTHES        23    // 6.6
#define GOOD_SUGAR        24    // 6
#define GOOD_LINEN        25    // 5.3
#define GOOD_FRUITS        26    // 5.3
#define GOOD_OIL    27    // 5
#define GOOD_FOOD     28  // 4
#define GOOD_COTTON        29    // 4
#define GOOD_LEATHER        30    // 3.6
#define GOOD_COPRA        31    // 3
#define GOOD_BRICKS    32    // 2.5
I hope the weight in initGoods.c is cwt, otherwise I've goofed :p
 
Actual value will vary wildly depending on whether the goods are import, export or contraband. But provided that unescorted merchants don't get any of, say, the first half dozen trade goods, and single merchants with heavy escort don't get anything from the bottom few, it should have the desired effect. Maybe move food up the list a bit and move linen down the list - I can imagine food being high enough priority to require an escort if it's going to a colony suffering from a famine or a siege, but I don't see linen as being important enough to warrant a three-ship escort for a single hold's worth of it. Unless it's the governor's new table-cloth. xD
 
Linen was rather important in the Caribbean. Shirts, undergarments, linings, and other sundries were highly desired because they were lightweight and breathable. Thus quite valuable. Take it from someone who has worn full kit (shirt, waistcoat, trousers, frock coat, belts, sash, headscarf, hat, baldric, bucket boots, and half a dozen things I've most likely forgotten) on a broiling hot (97 degree) day in Charlotte Amalie, St. Thomas. Anything cloth was linen, and I barely broke a sweat. Correcting the script for Blackbeard's Tower netted me an amazing amount of booze, I'm happy to say. Pirate's life.
 
Actual value will vary wildly depending on whether the goods are import, export or contraband. But provided that unescorted merchants don't get any of, say, the first half dozen trade goods, and single merchants with heavy escort don't get anything from the bottom few, it should have the desired effect. Maybe move food up the list a bit and move linen down the list - I can imagine food being high enough priority to require an escort if it's going to a colony suffering from a famine or a siege, but I don't see linen as being important enough to warrant a three-ship escort for a single hold's worth of it. Unless it's the governor's new table-cloth. xD
Linen was rather important in the Caribbean. Shirts, undergarments, linings, and other sundries were highly desired because they were lightweight and breathable. Thus quite valuable. Take it from someone who has worn full kit (shirt, waistcoat, trousers, frock coat, belts, sash, headscarf, hat, baldric, bucket boots, and half a dozen things I've most likely forgotten) on a broiling hot (97 degree) day in Charlotte Amalie, St. Thomas. Anything cloth was linen, and I barely broke a sweat. Correcting the script for Blackbeard's Tower netted me an amazing amount of booze, I'm happy to say. Pirate's life.
both good points! I'll leave it as is for now and we can balance it later when I've figured out a good way to distribute the loot xD

speaking of which, I'm trying a method to use the numbers now instead of the array. it's cleaner but I'm having a harder time visualizing what the do and what the odds are gonna be
Code:
    int iStart = GOOD_PLANKS + 1;// TIH we start after repair goods now for random cargo
    int iBootyQuality = 0;
 
    switch(iGetEncType){
        case 0: // Merchant 0: single merchant
            iBootyQuality = GOODS_QUANTITY - rand(8 - iShipClass);
        break;
        case 1: // Merchant 1: merchants with a light escort
            iBootyQuality = GOODS_QUANTITY - rand((8 - iShipClass) + 1);
        break;
        case 2: // Merchant 2: a single merchant with heavy escort
            iBootyQuality = GOODS_QUANTITY - 5 - rand((8 - iShipClass) + (iGetNumWarShips*2));
        break;
        case 3: // Patrol: a small patrol
            iBootyQuality = GOODS_QUANTITY - rand(5);
        break;
        case 4:
         
    }
 
    iBootyQuality = iClamp(iStart,GOODS_QUANTITY,iBootyQuality);

    // TIH --> we generate random different types now, instead of always 7 different types
    int randGoods = 1 + rand(6);
    for (int r=0;r<randGoods;r++)
    {    
        Fantom_SetCharacterGoods(rFantom, iBootyQuality, makeint(iMultiply * rand(iRandMultiply * 3)) );
        //Fantom_SetCharacterGoods(rFantom, iStart + rand(GOODS_QUANTITY - iStart - 1), makeint(iMultiply * rand(iRandMultiply * 3)) );
    }

there are many encounters left. but as a start, does that look like it'll work and give a roughly balanced distribution? and do warships drop loot? should they? and also how dramatically better should the chance for good booty be with harder encounters?
 
Last edited:
Back
Top