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

High Priority Levelling: Some Captains Not Correctly Initialized until Too Late

Then it must be a Treasure Quest Pirate OR a Shore Crewmembers one (that triggers extra encounters, including one that can trigger an enemy ship too).
But Treasure Quest pirates are supposed to DISAPPEAR after you completed the treasure quest. Also, there can only be one at a time.
Do you use Shore Crewmembers?
Ehm, nop. I didn't use shore crewmembers. Oh, I got it! It must be a Treasure Quest Pirate, becuase I have a Treasure Quest there also, on Hispaniola. If that's the case, then now I understand that.
 
And as fast as the lightning, I got a save when a ship surrenders. It's the same naval cutter that you see in the previous save uploaded here. You have to be careful and quick though; the ship it's almost going to sink (0% of hull health). But, I will let you also the screenshots about the naval cutter, including that bug with its cannons being bigger than it should be.

Naval cutter surrended.jpg Naval cutter surrended in my ship.jpg
Naval cutter big guns.jpg
 

Attachments

  • -=Player=- Open Sea October 19th, 1688.zip
    783.1 KB · Views: 350
This is definitely confirmed. I made several "attribute dumps" to see what is up with this guy.
Looks like there is some "resetting code" being applied to him at the moment I board the surrendered ship.

His skills change at the time of boarding; as if he was never properly initialized to begin with.
That might also explain why there would be any resetting done on him.
 
This problem seems to be caused because SetBaseShipData is called more often than it should be.

First I thought it was Levelling again and it turned out I wasn't 100% wrong there, because it is indeed part of CheckCharacterSetup :
Code:
void CheckCharacterSetup(ref chref)
{
   if (!CheckAttribute(chref,"id")) {chref.id = "without_id"; }
   if (!CheckAttribute(chref,"Experience")) {chref.Experience = 1; }
   if (!CheckAttribute(chref,"perks.FreePoints")){chref.perks.FreePoints = 1; }
   if (!CheckAttribute(chref,"skill.freeskill")){chref.skill.freeskill = 0; }
   if (!CheckAttribute(chref,"quest.officertype") || GetAttribute(chref,"quest.officertype") == "combat")
   {
     if(GetAttribute(chref,"isOfficer") == 1)
     {
       chref.quest.officertype = GetRandomOfficerType();
     }
     else
     {
       if(GetAttribute(chref,"issoldier") == 1)
       {
         chref.quest.officertype = OFFIC_TYPE_GUARD;
       }
       else
       {
         if(GetAttribute(chref,"isMerchant") == 1)
         {
           chref.quest.officertype = OFFIC_TYPE_SHOPKEEPER;
         }
         else
         {
           if(GetAttribute(chref,"isWarrior") == 1)
           {
             chref.quest.officertype = GetRandomEnemyType();
           }
           else
           {
             chref.quest.officerType = GetRandomNPCType();
           }
         }
       }
     }
   }
   if (CharacterHasShip(chref)) chref.quest.officerType = GetCaptainType(chref);
   if (!CheckAttribute(chref,"rank")) {chref.rank = 1; }
   if (!CheckAttribute(chref,"quest.officerprice") && !IsMainCharacter(chref)) chref.quest.officerprice = 0;
   if (!CheckAttribute(chref,"Money")) {
     chref.Money = GetRandCharMoney(chref, makeint(Rand(8)+2)); //Levis: Reduced amount of money characters carry
//   } else { // PB: Commented out, because zero money may be intentional!
//     if (sti(chref.Money) == 0) chref.Money = GetRandCharMoney(chref, makeint(Rand(8)+2));
   }
   //Checks for leaving officers
   if (!CheckAttribute(chref,"loyality")) {chref.loyality = 5+rand(15); }
   if (!CheckAttribute(chref,"alignment")) {if(rand(1)==1){chref.alignment = "good";}else{chref.alignment = "bad";}}
   if (!CheckAttribute(chref,"homelocation"))
   {
     int loc = FindLocation(chref.location);
     bool set = false;
     if(loc > -1)
     {
       if(GetAttribute(Locations[loc],"type") == "tavern")
       {
         chref.homelocation = "";
         chref.homelocation.group = "";
         chref.homelocation.locator = "";
         chref.homestate = "";
         set = true;
       }
     }
     if(!set)
     {
       chref.homelocation = chref.location; // PB: was alignment???
       chref.homelocation.group = chref.location.group;
       chref.homelocation.locator = chref.location.locator;
       if(CheckAttribute(chref,"chr_ai.type")) chref.homestate = chref.chr_ai.type;
       else chref.homestate = "citizen";
     }
   }
   SetBaseShipData(chref);
}
That is supposed to be called ONCE per character; after that, everything should be set up correctly and it doesn't need doing again.

But when I bypassed Levelling, it STILL happen. After a huge lot of digging, I finally found this:
Code:
// NK make this a separate function 05-05-11
bool Character_PostInit(int n)
{
   if(n >= CHARACTERS_QUANTITY) return false;
   ref rCharacter = GetCharacter(n);

   // NK 05-03-31 check to see if we're overwriting an animation -->
   if(!CheckAttribute(rCharacter,"model.animation") || rCharacter.model.animation == "")
   {
// changed by MAXIMUS [for AOP models] -->
     if(rCharacter.sex == "woman")
     {
       if(StraifCharacter(rCharacter)) rCharacter.model.animation = "new_woman";
       else rCharacter.model.animation = "towngirl";
// KK -->
       rCharacter.model.height = WOMAN_HEIGHT;
       rCharacter.capacity.max = WOMAN_CAPACITY;
// <-- KK
     }
     else
     {
       if(StraifCharacter(rCharacter)) rCharacter.model.animation = "new_man";
       else rCharacter.model.animation = "man";
// KK -->
       rCharacter.model.height = MAN_HEIGHT;
       rCharacter.capacity.max = MAN_CAPACITY;
// <-- KK
     }
// changed by MAXIMUS [for AOP models] <--
   }
   // NK <--
   rCharacter.FaceGroup = 0;

   // set fellows
   if (CheckAttribute(rCharacter,"fellows")) { SetBaseFellows(rCharacter); }
   // set base ship data
   SetBaseShipData(rCharacter);
But that code has been there FOREVER.
Looks like it is meant to be executed ONLY the first time a character has to be displayed, because it gets triggered by the animations not yet being initialized.

So it sounds like this problem is related to:
1. Quest captains NOT going through the Levelling system properly, so they get correctly initialized (and reset!) only AFTER the sea battle has completed
2. The first time a character has to be displayed as model, the ship gets reset too

For starters, I am getting rid of the Character_PostInit call to SetBaseShipData .
Then at least Levelling gets the FULL control over this and it isn't being handled in two places.

This only leaves the problem of quest captains not being initialized when they need to be for some reason.
That should probably be solved once this is done: Planned Feature - Use Generic Captain and Ship Generation Functions | PiratesAhoy!

In the end, this is yet another example of too many separate pieces of code existing to do the same thing. This makes debugging stupidly difficult.
So merging multiple functions for the same purpose into ONE is definitely something we should be doing as much as possible!
That does have the risk of temporarily breaking stuff, but having control in one spot makes fixing stuff so much easier than when everything is scattered everywhere. :modding
 
My earlier change had some rather unintended side-effects.
So in addition to that change, I'm also restoring some depreciated code from PROGRAM\Characters\characters_init.c:
Code:
  if(GetMainCharacterIndex()>=0)
   {
     SetMainCharacterIndex(GetMainCharacterIndex());
   }

   SetAllShipData(); // PB: If we make sure this is done FIRST, then it shouldn't need to occur in mid-game anymore
   SetAllFellows();  // PB: Just in case

     //Post init
   // do in PostInit()
   DoCharactersPostInit();
   /*for(n=0; n<TOTAL_CHARACTERS; n++)
     {
       // move to bottom as Character_PostInit(int n);
     }*/
   trace("Gauging: done second pass through char array");

   ReloadProgressUpdate();
   //LanguageCloseFile(tmpNameFileID);
}

void SetAllShipData()
{
   for(int i=0;i<CHARACTERS_QUANTITY;i++) // NK 05-04-05 use CHARACTERS_QUANTITY.
   {
     SetBaseShipData(GetCharacter(i));
   }
}

void SetAllFellows()
{
   ref rcc;
   for(int i=0;i<CHARACTERS_QUANTITY;i++) // NK 05-04-05 use CHARACTERS_QUANTITY
   {
     rcc = GetCharacter(i);
     if(CheckAttribute(rcc,"fellows"))
     {
       SetBaseFellows(rcc);
     }
   }
}
That should ensure ALL characters at least have their ships properly initialized at game start.

With a bit of luck, this may be enough to solve at least this particular issue in its entirety.

There would still be some left-over issues specifically for temporary quest captains, but those are likely to be fairly invisible.
Those will be addressed when this is being done: Planned Feature - Use Generic Captain and Ship Generation Functions | PiratesAhoy!
 
@salonikasurf: What type of captains did you notice this with?
If it were only certain types, it could be because different captain types are initialized in different ways (this still needs to be changed some time).

These are the different types that I can think of:
- Random WorldMap Ships
- Random Coast Raider Ships (around islands)
- Specific Main/Side Quest Ships
- General Quest Ships (Treasure Quest, Smuggling Coast Guard, Convoy Quest Enemy)

May get resolved once this is tackled: Planned Feature - Use Generic Captain and Ship Generation Functions | PiratesAhoy!
 
If I hear no confirmation and/or extra details on this by the end of next week, I am marking it as "Cannot Confirm".
At the moment I do not have enough information to be able to do anything.
 
I just captured a pirate Captain and hired him as an officer. Here are screenies of what has happened so far:
POTC4_2016_03_18_01_47_18_500.jpg POTC4_2016_03_18_02_15_43_427.jpg

Also since I can't seem to find that thread, the captured ship recovered all its health after being captured.
 
Last edited:
Also since I can't seem to find that thread, the captured ship recovered all its health after being captured.
Post moved to the thread you were looking for. :doff

What exact modpack version were you running? I made a change that I had hoped would prevent at least the ship HP issue.
But I think part of my fixes for that may have required a new game to be started, which I did not enforce until today.
Maybe that could be the reason?

What ship was this? Where was the encounter? Related to any sort of quest at all?

There is a larger underlying problem though that some captains at sea don't go through Levelling early enough.
We're going to have to fix that after Beta 4 was released, because I won't manage to do it earlier.
So there may be the occasional "skill reset" that occurs too late with captains. :(

Once this is done, things should get better:
Planned Feature - Use Generic Captain and Ship Generation Functions | PiratesAhoy!
But that is a relatively large change again which takes substantial time AND risks temporarily breaking stuff, so better not do that now....
 
This was with the very latest mod pack with the very latest ZIP and a new game. The ship was an English Bark at Turks where I was on a treasure quest. There was no treasure as expected as in my last game I went 1-8 in treasure quests by going 0-7 and then finally getting it on the 8th try.
 
Today I hired two surrendered Captains in two different installs. One old install and the latest install. This is what happened to the latest one in my current game.
POTC4_2016_03_18_04_21_46_382.jpg POTC4_2016_03_18_07_40_14_488.jpg

Yes he lost levels and perks.
 
This was with the very latest mod pack with the very latest ZIP and a new game.
Thanks for confirming. I'll put this back to the Bug Tracker then.

The ship was an English Bark at Turks where I was on a treasure quest.
A pirate ship on a Treasure Quest. That confirms my suspicions. Once I get to cleaning up this stuff, I think that should fix it:
Planned Feature - Use Generic Captain and Ship Generation Functions | PiratesAhoy!
It could very well be that this affects only the FIRST "Treasure Quest Pirate" and after that it is OK-(ish).

There was no treasure as expected as in my last game I went 1-8 in treasure quests by going 0-7 and then finally getting it on the 8th try.
Out of curiosity, what is your luck skill?
 
Currently it is only 4 AFAIK. I also suspect that only luck of 7 or better gets a full treasure chest.
 
Today I hired two surrendered Captains in two different installs.
What type of ship encounters were these? Any quests involved?

I think this is probably VERY related to: Fix in Progress - Captured ships regain full health on Capture Screen | PiratesAhoy!

At the moment, I think only Coast Raiders (random ships surrounding islands) and Worldmap Encounters are completely correctly initialized,
because those are the ones I had to manually fix because their initialization was so wrong that it caused CTDs before. :modding
 
Currently it is only 4 AFAIK. I also suspect that only luck of 7 or better gets a full treasure chest.
Whether there is anything in the Treasure Quest at all and how much there is, is all luck-dependent.

Based on the discussion here, I wonder if it should be related to luck at all:
Planned Feature - Replace "Luck Skill" with "Sneak" | PiratesAhoy!
We could make it 100% random, for example. Then you'd have to be lucky FOR REAL.
But at least you'd have a chance in the early game too.
 
Those were both pirate Captains from treasure quests.
Thanks. That confirms indeed the problem is what I think it is.
Annoying to be sure. But I have no time left to try and fix it. Maybe next week.... if we're really lucky.
 
Back
Top