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

Included in Build Companion Officer Duplication

Mere_Mortal

Free Like a Radical
Storm Modder
Seems like if I’ve pirated a ship then the captain is tagged as a “Pirate Captain”. That’s fine, but once they are put into the passenger list they should revert back to whatever officer role they have, or default to something. I don’t know why but some captains’ skills are always green, although my suspicion is that I captured them from a pirate ship as opposed to recruiting them in the tavern. In fact yes, the guy in the second image was definitely a pirate.

This isn’t a problem as long as they are the captain of a ship, but if all of their skills are always green then they are all used if I make them an officer, which is incredibly imbalanced since I could have 3 such officers with their role making no difference whatsoever.

In both images the officers are set as navigators; the first one is how it should look but the second one is all green.
 

Attachments

  • 1.jpg
    1.jpg
    165.8 KB · Views: 397
  • 2.jpg
    2.jpg
    163.2 KB · Views: 386
Last edited:
Looks like, for some reason, pirate captains are set to not contribute ANY skills at all:
Code:
   type = OFFIC_TYPE_CAPPIRATE;
   OfficerTypes.(type).skills.Leadership = 0;
   OfficerTypes.(type).skills.Leadership.importance = 6;
   OfficerTypes.(type).skills.Fencing = 0;
   OfficerTypes.(type).skills.Fencing.importance = 10;
   OfficerTypes.(type).skills.Sailing = 0;
   OfficerTypes.(type).skills.Sailing.importance = 3;
   OfficerTypes.(type).skills.Accuracy = 0;
   OfficerTypes.(type).skills.Accuracy.importance = 3;
   OfficerTypes.(type).skills.Cannons = 0;
   OfficerTypes.(type).skills.Cannons.importance = 5;
   OfficerTypes.(type).skills.Grappling = 0;
   OfficerTypes.(type).skills.Grappling.importance = 8;
   OfficerTypes.(type).skills.Repair = 0;
   OfficerTypes.(type).skills.Defence = 0;
   OfficerTypes.(type).skills.Commerce = 0;
   OfficerTypes.(type).skills.Sneak = 0;

Unless it goes green because there are other officers contributing their skills to him as he's in command of a ship.
 
There are two things going on here:

The captain’s skills are always green so long as he is the captain. That is logical because all skills matter for the captain.

The guy whose skills are all green is in the passenger list, his skills are always like that no matter which role I give him.
 

Attachments

  • 3.jpg
    3.jpg
    175.7 KB · Views: 369
Last edited:
Try to call the ResetEffectiveSkillAll function on that character and see if that puts it back to normal.
 
I ran this and it didn’t work...
Code:
 ResetEffectiveSkillAll(GetCharacter(1566))
I grabbed his attributes. I also forced oldofficertype to match his current role, didn’t do anything.
 

Attachments

  • compile.log
    7.9 KB · Views: 372
Last edited:
I keep changing his role in both the passenger and transfer interfaces, but it is being forced back to “Pirate Captain”.

This does nothing either...
Code:
   ref char = GetCharacter(1566)
   char.oldofficertype = "doctor"
   char.officertype = "doctor"
   char.skillsetup = "doctor"
   InitCharacterSkills(char)
 
Relevant code is this stuff:
Code:
void SetSumSkillData()
{
   ref chref = _refCh;
   string skill;
   int n;
   for(n = 0; n < 10; n++)
   {
     skill = GetSkillName(n);
     int skillval = GetShipSkill(chref,skill);
     int modval = CalcCharacterSkill(chref,skill);
     int color = COLOR_NORMAL;
     skill = "skill"+skill;
     GameInterface.strings.(skill) = skillval;
     if(skillVal < modval) color = COLOR_RED;
     if(skillVal > modval) color = COLOR_GREEN;
     if(skillVal==SKILL_MAX)   color = COLOR_MONEY;
     if(skillVal==0) color = COLOR_GRAY;
     ChangeStringColor(skill,color);
   }
}

void SetChrSkillData(ref chref)
{
   string skill;
   int n;
   for(n = 0; n < 10; n++)
   {
     skill = GetSkillName(n);
     int skillval = GetEffectiveSkill(chref,skill);
     int modval = CalcCharacterSkill(chref,skill);
     int color = COLOR_NORMAL;
     skill = "skill"+skill;
     GameInterface.strings.(skill) = modval;
     if(skillVal >= modval) color = COLOR_GREEN;
     if(skillVal <  modval) color = COLOR_MONEY;
     if(skillVal==0) color = COLOR_GRAY;
     ChangeStringColor(skill,color);
   }
// changed by MAXIMUS -->
   if(CheckAttribute(chref,"quest.officertype")==true) GameInterface.strings.CharacterName = chref.name + " " + chref.lastname + " - " + XI_ConvertString("S"+chref.quest.officertype); // MAXIMUS interface MOD
   else GameInterface.strings.CharacterName = chref.name + " " + chref.lastname + " - " + XI_ConvertString("SComrade-In-Arms");
//   GameInterface.strings.CharacterName = GetMyName(chref) + " - " + chref.quest.officertype;
// changed by MAXIMUS <--
}

Not sure which of those functions is applied to him, but it is probably 'SetChrSkillData'.
Probably 'skillval' and 'modval' are equal, which results in green text.
 
I keep changing his role in both the passenger and transfer interfaces, but it is being forced back to “Pirate Captain”.

This does nothing either...
Code:
   ref char = GetCharacter(1566)
   char.oldofficertype = "doctor"
   char.fficertype = "doctor"
   char.skillsetup = "doctor"
   InitCharacterSkills(char)
InitCharacterSkills is part of the dreaded Levelling system that has been driving me absolutely *** nuts this past year.
You shouldn't to call it though.

"char.fficertype = "doctor""
^ You have an "o" missing there and there should be a ".quest." in between too.
I'd also recommend using OFFIC_TYPE_DOCTOR instead of "doctor".

So just set char.QUEST.officertype = OFFIC_TYPE_DOCTOR; .
You should not even need to do anything else, because the code should notice the officer type changed and update the needed skills automatically.
 
Okay, well he’s not boosting the stats anyway because there are no contributing skills like you said. So it’s purely aesthetic, it just looks strange is all. I’ll look at that code a bit more.

I noticed the typo, but I’ll try that other stuff as well.
 
Okay, well he’s not boosting the stats anyway because there are no contributing skills like you said. So it’s purely aesthetic, it just looks strange is all. I’ll look at that code a bit more.
Is the guy a companion? This code is probably the reason:
Code:
int GetEffectiveSkillByValue(ref character, string skillName, int skillPoints)
{
   if(IsCompanion(character) || skillName == SKILL_FENCING) // PB: Perhaps treat ALL captains equally by adding CharacterHasShip?
   {
     return skillPoints;
   }

   if(CheckAttribute(character, "quest.officerType"))
   {
     return (skillPoints * GetOfficerSkillFactor(character, skillName) + 1) / 2;
   }
   
   return 0;
}
Specifically that first section. Otherwise the GetOfficerSkillFactor call should be returning zeros instead.

I noticed the typo, but I’ll try that other stuff as well.
I made an edit to my last post, because I said something that shouldn't actually be necessary.
 
He was a companion because I “borrowed” his ship and kept him as captain, but now he’s just moping about my deck.
Code:
   ref char = GetCharacter(1566)
   char.quest.oldofficertype = OFFIC_TYPE_DOCTOR
   char.quest.officertype = OFFIC_TYPE_DOCTOR
   char.skill.officertype = OFFIC_TYPE_DOCTOR
   char.skillsetup = OFFIC_TYPE_DOCTOR
   ResetEffectiveSkillAll(char)
   InitCharacterSkills(char)
He is bluntly being forced back to “Pirate Captain” no matter what I do.
 
It could very well be that InitCharacterSkills ends up somehow overriding the officer type.
So just set char.QUEST.officertype = OFFIC_TYPE_DOCTOR; .
You should not even need to do anything else, because the code should notice the officer type changed and update the needed skills automatically.
Though looking at it more, you may need to call the RestoreOfficerFromCaptain(ref officer) function too.
 
That did something... I can now change his role - sometimes, but it’s very random. Still all green, though.

Okay, skillsetup seem to be the one that’s locked to “Pirate Captain”. I’ve been deleting and setting the attributes over and over again but it keeps on reverting back. I think he’s drunk, that’s what the problem is.
 
I think "skillsetup" is only meant to set the character skill importances for NPCs levelling up.
But I don't know for sure. The Levelling system was never fully fixed and finished by the person who made it.
And I have already spent far too much time on it, trying to get it to behave. :facepalm
 
I think, but I can’t be too sure, that the problem is a duplicated passenger. Basically, the original transfer code does not remove an officer as a passenger from a companion, so they just fill up the passenger list. This went unnoticed since forever because nobody was ever looking at companion’s passenger lists, but I’m inquisitive like that. So anyway, this guy who has all-green skills just so happens to also be in command of a berthed ship, which I didn’t realise at first, and it’s quite possibly the ship I stolen borrowed in the first place. After grabbing the guy off the berthed ship, his skills were not all-green. Therefore, I was looking at his twin, and the skills were probably all-green because the chap was genuinely the captain of a ship.

Maybe the real bug here is passengers not being removed from companions?
 
The regular Is Companion check only checks if the guy is in any of your four companion slots, based on character index if I recall.
Are you saying you've got a copied officer with one of the copies as an actual Captain on a non berthed ship and the second copy as a regular officer???
 
Pretty much, yes. Except the ship he is captain of is berthed, and the twin is not in a active officer slot, not that it makes any difference either way.

I’m not entirely sure of the circumstances with this guy, but I can tell you this...

When a companion’s officer is removed from his position (as opposed to swapped with a passenger) he is not removed from their passenger list. I guess this was overlooked because it technically wasn’t possible to access their roster. This means that pretty much every player who has had a companion for some time and puts officers on them, will have a passengers list crammed with duplicates. Now bear in mind two twins will have the same index, so if one of them is my passenger and the other is in an officer slot, if I try to swap them then one will disappear.

So yeah, this guy with all-green skills was duplicated at some point. I can’t be sure but I will guess that I actually sold the ship he originally had because he’s now on a berthed heavy pinnace which I think is French. I probably gave him an officer role on a companion at some point because I don’t think captains are duplicated since they are literally swapped with a passenger (if they are removed, the ship sinks). In fact, I don’t think passengers are duplicated at all if it is a direct swap, only if an officer is removed.

What I’m thinking is that my new interface could present problems in respect of these duplicates. It certainly has caused me problems, sometimes I think it throws the passenger slot numbers out of sync especially if twins are both in the passenger list at the same time, which is certainly possible. So what I think would be necessary if the companion passenger lists do become accessible, is for twins to be searched for across all ships and forcibly removed (possibly prioritising them by companion number) - either that or a new game might be required otherwise people could have problems. I’ve started a new game, I think my officers and passengers are all screwed up now because of this so I have to start again to see how the new interface goes from scratch.

Note that my interface fixes this problem by properly removing an officer from the passenger list.
 
Last edited:
This is where the problem is with duplication; there is no RemovePassenger() function here...
Code:
void RemoveProcess()
{
   int i,j,n;
   string oldname;
   string lastname;

   i = GetCompanionIndex(refMyCharacter,nMyCharacterCompanionPlace);
   if(i<0) return;

   if(nFourImageNum>0)
   {
     j = SetOfficersIndex(GetCharacter(i),nFourImageNum,-1);
     if(j>0)   AddPassenger(refMyCharacter,GetCharacter(j),false);
   }
   else
   {
     for(j=1; j<4; j++)
     {
       n = SetOfficersIndex(GetCharacter(i),j,-1);
       if(n>=0) AddPassenger(refMyCharacter,GetCharacter(n),false);
     }
     SetCompanionIndex(refMyCharacter,nMyCharacterCompanionPlace,-1);
     if(i!=sti(refEnemyCharacter.index))
     {
       IDeleteShipAttributes(GetCharacter(i));
     }
     AddPassenger(refMyCharacter,GetCharacter(i),false);
   }
   RefreshScreen();
   SetSelectable("REMOVE_BUTTON",false);
   if(GetNotCaptivePassenger(refMyCharacter,0)!=-1)   SetCurrentNode("PASSENGERS_LIST");
   else   SetCurrentNode("COMPAIN_LIST");
}


And I’ve edited the topic title, I think it describes the matter more accurately.
 
Last edited:
What does AddPassenger do when the character is already a passenger? I'd imagine it just sets something that was already set and would do no harm.
But I'm not sure of that....

How would a passenger have to get removed in that section of the interface?
 
I actually have no idea why AddPassenger() is there twice, I did wonder about that. It doesn’t add them again, though.
How would a passenger have to get removed in that section of the interface?
How or why? If I understand correctly, RemovePassenger() should also be called whenever AddPassenger() is.

This is an example of how I use the button (no point checking if the officer index exists, button should be disabled if not)...
Code:
void RemoveProcess()
{
   if (numFourImage > 0) {
     n = SetOfficersIndex(refShip2,numFourImage,-1)
     AddPassenger(refShip1,GetCharacter(n),-1)
     RemovePassenger(refShip2,GetCharacter(n))
     SetCurrentNode("TITLE")
     RefreshScreen()
   }
}
 
Last edited:
Back
Top