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

WIP Improvements to Smuggling.

If you're giving the hint at the place where you're doing the selling, another possible source is the soldier who told you the best time to land. Either explicitly ("By the way, I can't stay long because they've got us running extra patrols these days") or by the length of time he says you can go. If it's 1 hour then patrol level is high, if it's 3 hours then patrol level is low, and if it's 12 hours then he's probably lying (I've already figured out that the last one seems to be the case).

What is this 1 hour, 3 hour, 12 hour thing? For me it is 20 minutes.
 
I also had a 20 minute timeframe on high patrol state, so maybe 3 and 1 is for low and normal state.

So I've been doing some coding on the smuggling things and added more hints to how the system works and what patrol state the island is on etc, and it seems to work well

But I've been having a crash sometimes when returning to the ship after sealing the deal on the beach
these are the last errors:
Code:
RUNTIME ERROR - file: smuggling.c; line: 1386
missed attribute: island
RUNTIME ERROR - file: smuggling.c; line: 1386
no rAP data
RUNTIME ERROR - file: smuggling.c; line: 1386
invalid index -1 [size:24]
RUNTIME ERROR - file: smuggling.c; line: 1386
function 'FindCoastGuardLocator' stack error
RUNTIME ERROR - file: smuggling.c; line: 1433
Using reference variable without initializing

they don't seem to be my fault tho, the lines are from opium functions, which I haven't touched

The functions with the lines marked:
Code:
int getOpiumCaughtChance()
{
    ref Pchar = GetMainCharacter();
    if (GetAttribute(Pchar         , "vcskip") == true)    return 0;
    if (GetAttribute(LoadedLocation, "vcskip") == true)    return 0;
    int chance = 100;
    //Take difficulty into account:
    chance = chance - (50-GetDifficulty()*10);
    float mult = 1;
    //Take smuggling perks into account:
    if(CheckCharacterPerk(Pchar,"ImproveSmuggling")) mult = mult - 0.10;
    if(CheckCharacterPerk(Pchar,"AdvanceSmuggling")) mult = mult - 0.15;
    //At night you wont be detected that easy


    if(!isDay())
    {
        mult = mult - 0.5;
    } <<<<<< Line 1386  <<<<<<<<


    chance = makeint(round(chance*mult));
    return chance;
}

Code:
void UseOpium(ref User)
{
    //Remove 1 opium
    ref pchar = GetMainCharacter();
//    TakeItemFromCharacter(User, "opium"); // PB: This is already handled elsewhere
    //Lets check all effects
    OpiumEffects(User);
    //Set Opium Sickness
    float sickness = 0.2;
    if(CheckAttribute(pchar,"quest.opium_use.opiumsickness")) sickness = sickness + stf(User.quest.opium_use.opiumsickness);

    User.quest.opium_use.opiumsickness = sickness; <<<<< Line 1433 <<<<<<<

    //Remove the opium sickness in X days.
    int opiumuses = 0;
    if(CheckAttribute(pchar,"quest.opium_use.amount")) opiumuses = sti(pchar.quest.opium_use.amount);
    opiumuses++;
    int days = makeint(sickness*10/2);
    pchar.quest.opium_use.amount = opiumuses;
    string questname = "remove_opium_effect_"+opiumuses;
    pchar.quest.opium_use.users.(questname).userid = User.id;
    pchar.quest.(questname).win_condition.l1 = "Timer";
    pchar.quest.(questname).win_condition.l1.date.day = GetAddingDataDay(0, 0, days);
    pchar.quest.(questname).win_condition.l1.date.month = GetAddingDataMonth(0, 0, days);
    pchar.quest.(questname).win_condition.l1.date.year = GetAddingDataYear(0, 0, days);
    pchar.quest.(questname).win_condition = "remove_opium_effect";
}

I wasn't smuggling opium and definitely not using it, but I did the smuggling start where I think you start with opium on you, so might have been in the inventory.

I didn't manage to reproduce the error a lot of times, but my guess is it has something to do with getting caught with opium at night considering one of the failing lines has to do with time of day. maybe when it spawns a ship? because I did encounter a coast guard ship at day once, and I only got the crash at night. it might be coincidence since I didn't manage to reproduce it very many times.

last things in compile.log:
Code:
SMUGGLING Stop event
Quest name Rand_SmugglingRemove FOUND in CommonQuestComplete
Quest name Made First Smuggling Report FOUND in SideQuestComplete
SMUGGLING load Coastguard patrol and pursuit

or maybe it's trying to spawn soldiers on the ship? I really don't know..

The rest is coming along fine, trying to come up with some interesting random lines and optimally a fun persuasion system for the guard
 
Error log on a line that has only a bracket?
Agh, those are the worst. Generally means there is an error somewhere, but the game code cannot figure out the actual location.
It might be somewhere else altogether. :facepalm
 
Error log on a line that has only a bracket?
Agh, those are the worst. Generally means there is an error somewhere, but the game code cannot figure out the actual location.
It might be somewhere else altogether. :facepalm
Oh boy, there goes my weekend :p

well, best case scenario:
Code:
string FindCoastGuardLocator(bool BySea)
{
    aref reloads, reloadref;
    int i;
    if(BySea)
    {
        //By Sea
        ref island = &Islands[FindIsland(loadedlocation.island)];
        makearef(reloads,island.reload);
        for(i=0;i<GetAttributesNum(reloads);i++)
        {
            reloadref = GetAttributeN(reloads,i);
            if(reloadref.go == loadedlocation.id)
            {
                return reloadref.emerge;
            }
        }
        
    }
    else
    {
        //By Land
        makearef(reloads,loadedlocation.reload);
        for(i=0;i<GetAttributesNum(reloads);i++)
        {
            reloadref = GetAttributeN(reloads,i);
            if(reloadref.label == "Jungle.")
            {
                return reloadref.name;
            }
        }
    }
    return "";
}

if the error is still in the file and not somewhere else, this is the only place that uses "island" as a ref and not sisland or curisland or somesuch. it's in the "//By sea" section in a function that apparently got to do with locators too, so I'm hopeful it's there! the downside is that I can't make heads or tails of the function, which makes it hard to troubleshoot :eek:
 
Make a copy of your modified file.
Revert the copy in the game to the original version.
See if the problem persists or if it disappears.

If it persists, it is a bug with the mod.
If not, you can use WinMerge to move your own changes back in to see when the problem returns.

That's the only way I know to narrow down where a problem originates.
I've had to do that many times myself....
 
I took a lot of tries but I eventually got the same error with the original file, at different lines
Code:
RUNTIME ERROR - file: smuggling.c; line: 1528
missed attribute: island
RUNTIME ERROR - file: smuggling.c; line: 1528
no rAP data
RUNTIME ERROR - file: smuggling.c; line: 1528
invalid index -1 [size:24]
RUNTIME ERROR - file: smuggling.c; line: 1528
function 'FindCoastGuardLocator' stack error
RUNTIME ERROR - file: smuggling.c; line: 1578
Using reference variable without initializing

This time it's at lines that make more sense
Code:
string FindCoastGuardLocator(bool BySea)
{
    aref reloads, reloadref;
    int i;
    if(BySea)
    {
        //By Sea

        ref island = &Islands[FindIsland(loadedlocation.island)]; <<<<<< 1528 <<<<<<

        makearef(reloads,island.reload);
        for(i=0;i<GetAttributesNum(reloads);i++)
        {
            reloadref = GetAttributeN(reloads,i);
            if(reloadref.go == loadedlocation.id)
            {
                return reloadref.emerge;
            }
        }
       
    }
    else
    {
        //By Land
        makearef(reloads,loadedlocation.reload);
        for(i=0;i<GetAttributesNum(reloads);i++)
        {
            reloadref = GetAttributeN(reloads,i);
            if(reloadref.label == "Jungle.")
            {
                return reloadref.name;
            }
        }
    }
    return "";
}

Code:
void CreateCoastGuardPatrol()
{
    ref PChar = GetMainCharacter();
    ref sld;
    if(DEBUG_SMUGGLING>1) trace("SMUGGLING load Coastguard patrol and pursuit");
    //Levis add smuggling perk -->
    float largegroup_chance = 100.0;
    if(CheckCharacterPerk(Pchar,"ImproveSmuggling"))
    {
        largegroup_chance = largegroup_chance*0.5;
    }
    largegroup_chance = 100;
    //<-- smuggling perk
    string group = "reload";
    string locator;
    int fromseachance = 50;
    if(CheckCharacterPerk(Pchar,"AdvanceSmuggling"))
    {
        fromseachance = fromseachance*0.5;
    }
    if(rand(100)<fromseachance)
    {
        locator = FindCoastGuardLocator(true); <<<<<< 1578 <<<<<<<
        Pchar.quest.contraband.fromsea = true;
    }
    else
    {
        locator = FindCoastGuardLocator(false);
        Pchar.quest.contraband.fromsea = false;
    }
[continues]

So it seems these functions are called before things they are dependent on are initiated or after they are deleted. it'll take some digging to figure it out I guess..

I guess the crash is rare enough that it hasnt been reported. maybe I interrupted the event where the coast guard finds me and spawns by boarding the ship in the middle of it, thus messing things up?
 
Maybe? I do know it is a very complex system, so I wouldn't be surprised...
 
since it seems to be an old, rare and hard to track down bug I'll leave be for now :p

looking thru the code, it's wild how many variables there are! :bounce such a lot of things that affects the chance to get caught even if you don't find the correct time for shift change/breakfast. apart from skills and perks, weather also plays a huge part, and you even got less chance to be found on a moonless night! it's cool, but there's pretty much no clues to those things in game so most will never know. so I've expanded the smuggling book a lot! It's so much I almost worry people won't have the patience to read it :p

I think the smuggling is really taking shape! still got some things I want to do, like the persuasion dialog with the guard, tweaking some other dialogs and I'm sure the new (and old) numbers still need some balancing, but I got high hopes smuggling will be a more viable choice!

I'll list the things I remember changing
-many more variables in calculating chance of officer succeeding in getting patrol times
-more variables for bad info, chance decreases exponentially with stats. ie you still got a large chance with low stats, but it decreases much faster. function also takes a character argument now, so officers got a separate chance from the player. choices!
-more ways to find out the patrol level of the island, eg thru tavern rumours
-more hints and explanations during dialog
-greatly(SRSLY) expanded smuggling book
-higher prices with higher patrol level
-new calculation for chance of getting caught (not entirely happy with it yet, it's still too linear, but I'm bad at math)
-maybe other things

the chance of getting caught is still run every 5 sec; it should be changed, but I don't know how yet. I had a 60% chance of being found and still managed to get away a lot of the time, so I fear running it once every 30 sec is will be too easy. pausing the event when in dialog is probably a good idea tho, if I figure out how to do it :shrug

theyre wildly WIP, but definitely playable, so attaching the files! things like the persuasion will take some more thought.. but I figure it'll be easier to balance what I got if more people got the chance to try it xD
 

Attachments

  • Smuggling.rar
    78.2 KB · Views: 90
pausing the event when in dialog is probably a good idea tho, if I figure out how to do it :shrug
I think there is an attribute you can use for that.
Look in AICameras.c (I think) and search for my comment "don't bother me when I'm flying" (seriously! :razz ).
 
I think there is an attribute you can use for that.
Look in AICameras.c (I think) and search for my comment "don't bother me when I'm flying" (seriously! :razz ).
Found it in LAI_events, but I didn't quite manage to translate it to my case :eek: it was under "bool LAi_Character_CanDialog(aref chr, aref by)" which seems to check if the character is available for talking? I realised rn that probably that returns false when character is in dialog as they can't initiate another.. but oh well, making a note for later I guess

what I did instead was create a new function called PauseCoastGuardCheck
Code:
void CheckCoastGuard()
{
    ref PChar = GetMainCharacter();
    if(PChar.location == PChar.quest.contraband.CurrentPlace)
    {
        float chance_get_caught = GetEventData();
        if(Rand((100*SMUGGLING_TIME_CHANCE_MULT))<=chance_get_caught)
        {
            if(DEBUG_SMUGGLING>1) TraceAndLog("SMUGGLING Coastguard found you!");
            Lai_QuestDelay("Rand_ContrabandInterruption",1.0);
            StopCoastGuardCheck();
        }
        if(DEBUG_SMUGGLING>1) TraceAndLog("SMUGGLING caught chance is "+chance_get_caught+" in "+(100*SMUGGLING_TIME_CHANCE_MULT));
        if(DEBUG_SMUGGLING>1) TraceAndLog("SMUGGLING Evaded the Coastguard (for now)");
    }
    if(dialogRun || dialogSelf){
        SetEventHandler("PauseCoastGuardCheck","PauseCoastGuardCheck",1);
        PostEvent("PauseCoastGuardCheck",5000,"f",chance_get_caught);      
    }
    else PostEvent("CheckCoastGuard",5000,"f",chance_get_caught);
}

void PauseCoastGuardCheck()
{
    if(DEBUG_SMUGGLING>1) TraceAndLog("SMUGGLING paused during conversation");
    float chance_get_caught = GetEventData();
    if(!dialogRun && !dialogSelf) PostEvent("CheckCoastGuard",5000,"f",chance_get_caught);
    else PostEvent("PauseCoastGuardCheck",5000,"f",chance_get_caught);
}

it's called from CheckCoastGuard if dialogRun or dialogSelf (which is useless rn, but it's for future proofing I guess) is true. as you can see PauseCoastGuardCheck does nothing but save the caught chance and checks if the character is in dialog every 5 seconds. "spinning the disc", so to speak. when dialog ends it returns to CheckCoastGuard again. the event is deleted in StopCoastGuardCheck

I might have goofed as I don't quite know what I'm doing, but it seems to work so far!
 

Attachments

  • smuggling.c
    68.9 KB · Views: 105
First snag: that file uses a different character at the end of each line.

Second problem: you have a 'switch(sti(sisland.smuggling_nation))' block which includes 'case AMERICA' and has the option to later include 'case SWEDEN'. As both of these are "guest nation 1", they both translate to number 6. If you include 'case SWEDEN', it will override the settings for 'case AMERICA' as they're effectively both the same. It's not a problem now as 'case SWEDEN' is commented out, but if you want to implement it, you'll perhaps need to check the current period. Use the settings for Sweden in "Spanish Main", "Golden Age of Piracy" and "Colonial Powers"; and use the settings for America in "Revolutions" and "Napoleonic".
 
First snag: that file uses a different character at the end of each line.
I don't know what this means :(
Second problem: you have a 'switch(sti(sisland.smuggling_nation))' block which includes 'case AMERICA' and has the option to later include 'case SWEDEN'. As both of these are "guest nation 1", they both translate to number 6. If you include 'case SWEDEN', it will override the settings for 'case AMERICA' as they're effectively both the same. It's not a problem now as 'case SWEDEN' is commented out, but if you want to implement it, you'll perhaps need to check the current period. Use the settings for Sweden in "Spanish Main", "Golden Age of Piracy" and "Colonial Powers"; and use the settings for America in "Revolutions" and "Napoleonic".
That makes a lot of sense, good call! gonna fix that :onya
 
It means if I try to edit the file, it looks like this:
edit_screenshot.jpg
It also means WinMerge complains "These files use different carriage return types." I don't know why that happened this time because it hasn't happened with other files that you've uploaded.
 
It means if I try to edit the file, it looks like this:
View attachment 31062
It also means WinMerge complains "These files use different carriage return types." I don't know why that happened this time because it hasn't happened with other files that you've uploaded.
:shock no idea why that would happen! maybe I accidentally pushed something and it got saved some weird encoding, I dont even know what carriage is. I'll check and upload a new one in a few minutes
 
I still don't know why that happened, but I think I managed to fix it by closing and reopening the file.. gotta keep an eye on that I guess
 

Attachments

  • smuggling.c
    70.8 KB · Views: 100
It means if I try to edit the file, it looks like this:
View attachment 31062
It also means WinMerge complains "These files use different carriage return types." I don't know why that happened this time because it hasn't happened with other files that you've uploaded.

Yep - I opened it in wordpad rather than notepad to get a sensible layout for a quick look at the code, but the carriage returns certainly got screwed. I can live with the extra contraband item on alert level as I rehash import/export items but may have to change what they are - but I don't think it makes any realistic sense. However I see pirate nation gets contraband - which makes sense if you capture colonies on for them perhaps. I hadn't thought about the player re-distributing island ownerships (and thereby contraband) in my thoughts about trade runs. I guess I just have to accept that they can be manipulated in that way - no easy solution I can think of for now.
 
Carriage return is the character which marks the end of a line. In some systems it's ASCII 10, in some it's ASCII 13, and in some it's both of those.

Looking at the older version of "smuggling.c", and at another random .c file, using Hex Editor, it seems the files normally end their lines with both 13 and 10. Your new version ends lines with just 10.
 
Carriage return is the character which marks the end of a line. In some systems it's ASCII 10, in some it's ASCII 13, and in some it's both of those.

Looking at the older version of "smuggling.c", and at another random .c file, using Hex Editor, it seems the files normally end their lines with both 13 and 10. Your new version ends lines with just 10.
Definitely, in notepad++ I made formatting characters visible and all line breaks had become LF, and in all other files they were CFLF. I suspect I accidentally changed encoding to UTF-8, that seemed to have that effect.. but I'm not sure. shouldn't be a problem now at least
 
Back
Top